Add glide.yaml and vendor deps
This commit is contained in:
parent
db918f12ad
commit
5b3d5e81bd
18880 changed files with 5166045 additions and 1 deletions
67
vendor/k8s.io/kubernetes/pkg/kubelet/cm/BUILD
generated
vendored
Normal file
67
vendor/k8s.io/kubernetes/pkg/kubelet/cm/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cgroup_manager_linux.go",
|
||||
"container_manager.go",
|
||||
"container_manager_linux.go",
|
||||
"container_manager_stub.go",
|
||||
"helpers_linux.go",
|
||||
"pod_container_manager_linux.go",
|
||||
"pod_container_manager_stub.go",
|
||||
"types.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/resource:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/kubelet/cadvisor:go_default_library",
|
||||
"//pkg/kubelet/cm/util:go_default_library",
|
||||
"//pkg/kubelet/qos:go_default_library",
|
||||
"//pkg/types:go_default_library",
|
||||
"//pkg/util:go_default_library",
|
||||
"//pkg/util/errors:go_default_library",
|
||||
"//pkg/util/mount:go_default_library",
|
||||
"//pkg/util/oom:go_default_library",
|
||||
"//pkg/util/procfs:go_default_library",
|
||||
"//pkg/util/runtime:go_default_library",
|
||||
"//pkg/util/sets:go_default_library",
|
||||
"//pkg/util/sysctl:go_default_library",
|
||||
"//pkg/util/wait:go_default_library",
|
||||
"//vendor:github.com/blang/semver",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:github.com/opencontainers/runc/libcontainer/cgroups",
|
||||
"//vendor:github.com/opencontainers/runc/libcontainer/cgroups/fs",
|
||||
"//vendor:github.com/opencontainers/runc/libcontainer/cgroups/systemd",
|
||||
"//vendor:github.com/opencontainers/runc/libcontainer/configs",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"cgroup_manager_linux_test.go",
|
||||
"container_manager_linux_test.go",
|
||||
"helpers_linux_test.go",
|
||||
],
|
||||
library = "go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/resource:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/util/mount:go_default_library",
|
||||
"//vendor:github.com/stretchr/testify/assert",
|
||||
"//vendor:github.com/stretchr/testify/require",
|
||||
],
|
||||
)
|
||||
454
vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux.go
generated
vendored
Normal file
454
vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,454 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
|
||||
cgroupsystemd "github.com/opencontainers/runc/libcontainer/cgroups/systemd"
|
||||
libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
|
||||
// libcontainerCgroupManagerType defines how to interface with libcontainer
|
||||
type libcontainerCgroupManagerType string
|
||||
|
||||
const (
|
||||
// libcontainerCgroupfs means use libcontainer with cgroupfs
|
||||
libcontainerCgroupfs libcontainerCgroupManagerType = "cgroupfs"
|
||||
// libcontainerSystemd means use libcontainer with systemd
|
||||
libcontainerSystemd libcontainerCgroupManagerType = "systemd"
|
||||
)
|
||||
|
||||
// ConvertCgroupNameToSystemd converts the internal cgroup name to a systemd name.
|
||||
// For example, the name /Burstable/pod_123-456 becomes Burstable-pod_123_456.slice
|
||||
// If outputToCgroupFs is true, it expands the systemd name into the cgroupfs form.
|
||||
// For example, it will return /Burstable.slice/Burstable-pod_123_456.slice in above scenario.
|
||||
func ConvertCgroupNameToSystemd(cgroupName CgroupName, outputToCgroupFs bool) string {
|
||||
name := string(cgroupName)
|
||||
result := ""
|
||||
if name != "" && name != "/" {
|
||||
// systemd treats - as a step in the hierarchy, we convert all - to _
|
||||
name = strings.Replace(name, "-", "_", -1)
|
||||
parts := strings.Split(name, "/")
|
||||
for _, part := range parts {
|
||||
// ignore leading stuff for now
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
if len(result) > 0 {
|
||||
result = result + "-"
|
||||
}
|
||||
result = result + part
|
||||
}
|
||||
} else {
|
||||
// root converts to -
|
||||
result = "-"
|
||||
}
|
||||
// always have a .slice suffix
|
||||
result = result + ".slice"
|
||||
|
||||
// if the caller desired the result in cgroupfs format...
|
||||
if outputToCgroupFs {
|
||||
var err error
|
||||
result, err = cgroupsystemd.ExpandSlice(result)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error adapting cgroup name, input: %v, err: %v", name, err))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ConvertCgroupFsNameToSystemd converts an expanded cgroupfs name to its systemd name.
|
||||
// For example, it will convert test.slice/test-a.slice/test-a-b.slice to become test-a-b.slice
|
||||
// NOTE: this is public right now to allow its usage in dockermanager and dockershim, ideally both those
|
||||
// code areas could use something from libcontainer if we get this style function upstream.
|
||||
func ConvertCgroupFsNameToSystemd(cgroupfsName string) (string, error) {
|
||||
// TODO: see if libcontainer systemd implementation could use something similar, and if so, move
|
||||
// this function up to that library. At that time, it would most likely do validation specific to systemd
|
||||
// above and beyond the simple assumption here that the base of the path encodes the hierarchy
|
||||
// per systemd convention.
|
||||
return path.Base(cgroupfsName), nil
|
||||
}
|
||||
|
||||
// libcontainerAdapter provides a simplified interface to libcontainer based on libcontainer type.
|
||||
type libcontainerAdapter struct {
|
||||
// cgroupManagerType defines how to interface with libcontainer
|
||||
cgroupManagerType libcontainerCgroupManagerType
|
||||
}
|
||||
|
||||
// newLibcontainerAdapter returns a configured libcontainerAdapter for specified manager.
|
||||
// it does any initialization required by that manager to function.
|
||||
func newLibcontainerAdapter(cgroupManagerType libcontainerCgroupManagerType) *libcontainerAdapter {
|
||||
return &libcontainerAdapter{cgroupManagerType: cgroupManagerType}
|
||||
}
|
||||
|
||||
// newManager returns an implementation of cgroups.Manager
|
||||
func (l *libcontainerAdapter) newManager(cgroups *libcontainerconfigs.Cgroup, paths map[string]string) (libcontainercgroups.Manager, error) {
|
||||
switch l.cgroupManagerType {
|
||||
case libcontainerCgroupfs:
|
||||
return &cgroupfs.Manager{
|
||||
Cgroups: cgroups,
|
||||
Paths: paths,
|
||||
}, nil
|
||||
case libcontainerSystemd:
|
||||
// this means you asked systemd to manage cgroups, but systemd was not on the host, so all you can do is panic...
|
||||
if !cgroupsystemd.UseSystemd() {
|
||||
panic("systemd cgroup manager not available")
|
||||
}
|
||||
return &cgroupsystemd.Manager{
|
||||
Cgroups: cgroups,
|
||||
Paths: paths,
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("invalid cgroup manager configuration")
|
||||
}
|
||||
|
||||
func (l *libcontainerAdapter) revertName(name string) CgroupName {
|
||||
if l.cgroupManagerType != libcontainerSystemd {
|
||||
return CgroupName(name)
|
||||
}
|
||||
|
||||
driverName, err := ConvertCgroupFsNameToSystemd(name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
driverName = strings.TrimSuffix(driverName, ".slice")
|
||||
driverName = strings.Replace(driverName, "_", "-", -1)
|
||||
return CgroupName(driverName)
|
||||
}
|
||||
|
||||
// adaptName converts a CgroupName identifer to a driver specific conversion value.
|
||||
// if outputToCgroupFs is true, the result is returned in the cgroupfs format rather than the driver specific form.
|
||||
func (l *libcontainerAdapter) adaptName(cgroupName CgroupName, outputToCgroupFs bool) string {
|
||||
if l.cgroupManagerType != libcontainerSystemd {
|
||||
name := string(cgroupName)
|
||||
return name
|
||||
}
|
||||
return ConvertCgroupNameToSystemd(cgroupName, outputToCgroupFs)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
// simplifies interaction with libcontainer and its cgroup managers
|
||||
adapter *libcontainerAdapter
|
||||
}
|
||||
|
||||
// Make sure that cgroupManagerImpl implements the CgroupManager interface
|
||||
var _ CgroupManager = &cgroupManagerImpl{}
|
||||
|
||||
// NewCgroupManager is a factory method that returns a CgroupManager
|
||||
func NewCgroupManager(cs *CgroupSubsystems, cgroupDriver string) CgroupManager {
|
||||
managerType := libcontainerCgroupfs
|
||||
if cgroupDriver == string(libcontainerSystemd) {
|
||||
managerType = libcontainerSystemd
|
||||
}
|
||||
return &cgroupManagerImpl{
|
||||
subsystems: cs,
|
||||
adapter: newLibcontainerAdapter(managerType),
|
||||
}
|
||||
}
|
||||
|
||||
// Name converts the cgroup to the driver specific value in cgroupfs form.
|
||||
func (m *cgroupManagerImpl) Name(name CgroupName) string {
|
||||
return m.adapter.adaptName(name, true)
|
||||
}
|
||||
|
||||
// CgroupName converts the literal cgroupfs name on the host to an internal identifier.
|
||||
func (m *cgroupManagerImpl) CgroupName(name string) CgroupName {
|
||||
return m.adapter.revertName(name)
|
||||
}
|
||||
|
||||
// buildCgroupPaths builds a path to each cgroup subsystem for the specified name.
|
||||
func (m *cgroupManagerImpl) buildCgroupPaths(name CgroupName) map[string]string {
|
||||
cgroupFsAdaptedName := m.Name(name)
|
||||
cgroupPaths := make(map[string]string, len(m.subsystems.MountPoints))
|
||||
for key, val := range m.subsystems.MountPoints {
|
||||
cgroupPaths[key] = path.Join(val, cgroupFsAdaptedName)
|
||||
}
|
||||
return cgroupPaths
|
||||
}
|
||||
|
||||
// Exists checks if all subsystem cgroups already exist
|
||||
func (m *cgroupManagerImpl) Exists(name CgroupName) bool {
|
||||
// Get map of all cgroup paths on the system for the particular cgroup
|
||||
cgroupPaths := m.buildCgroupPaths(name)
|
||||
|
||||
// If even one cgroup path doesn't exist, then the cgroup doesn't exist.
|
||||
for _, path := range cgroupPaths {
|
||||
if !libcontainercgroups.PathExists(path) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Destroy destroys the specified cgroup
|
||||
func (m *cgroupManagerImpl) Destroy(cgroupConfig *CgroupConfig) error {
|
||||
cgroupPaths := m.buildCgroupPaths(cgroupConfig.Name)
|
||||
|
||||
// we take the location in traditional cgroupfs format.
|
||||
abstractCgroupFsName := string(cgroupConfig.Name)
|
||||
abstractParent := CgroupName(path.Dir(abstractCgroupFsName))
|
||||
abstractName := CgroupName(path.Base(abstractCgroupFsName))
|
||||
|
||||
driverParent := m.adapter.adaptName(abstractParent, false)
|
||||
driverName := m.adapter.adaptName(abstractName, false)
|
||||
|
||||
// this is an ugly abstraction bleed, but systemd cgroup driver requires full paths...
|
||||
if m.adapter.cgroupManagerType == libcontainerSystemd {
|
||||
driverName = m.adapter.adaptName(cgroupConfig.Name, false)
|
||||
}
|
||||
|
||||
// Initialize libcontainer's cgroup config with driver specific naming.
|
||||
libcontainerCgroupConfig := &libcontainerconfigs.Cgroup{
|
||||
Name: driverName,
|
||||
Parent: driverParent,
|
||||
}
|
||||
|
||||
manager, err := m.adapter.newManager(libcontainerCgroupConfig, cgroupPaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete cgroups using libcontainers Managers Destroy() method
|
||||
if err = manager.Destroy(); err != nil {
|
||||
return fmt.Errorf("Unable to destroy cgroup paths for cgroup %v : %v", cgroupConfig.Name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type subsystem interface {
|
||||
// Name returns the name of the subsystem.
|
||||
Name() string
|
||||
// Set the cgroup represented by cgroup.
|
||||
Set(path string, cgroup *libcontainerconfigs.Cgroup) error
|
||||
}
|
||||
|
||||
// Cgroup subsystems we currently support
|
||||
var supportedSubsystems = []subsystem{
|
||||
&cgroupfs.MemoryGroup{},
|
||||
&cgroupfs.CpuGroup{},
|
||||
}
|
||||
|
||||
// setSupportedSubsytems sets cgroup resource limits only on the supported
|
||||
// subsytems. ie. cpu and memory. We don't use libcontainer's cgroup/fs/Set()
|
||||
// method as it doesn't allow us to skip updates on the devices cgroup
|
||||
// Allowing or denying all devices by writing 'a' to devices.allow or devices.deny is
|
||||
// not possible once the device cgroups has children. Once the pod level cgroup are
|
||||
// created under the QOS level cgroup we cannot update the QOS level device cgroup.
|
||||
// We would like to skip setting any values on the device cgroup in this case
|
||||
// but this is not possible with libcontainers Set() method
|
||||
// See https://github.com/opencontainers/runc/issues/932
|
||||
func setSupportedSubsytems(cgroupConfig *libcontainerconfigs.Cgroup) error {
|
||||
for _, sys := range supportedSubsystems {
|
||||
if _, ok := cgroupConfig.Paths[sys.Name()]; !ok {
|
||||
return fmt.Errorf("Failed to find subsytem mount for subsytem: %v", sys.Name())
|
||||
}
|
||||
if err := sys.Set(cgroupConfig.Paths[sys.Name()], cgroupConfig); err != nil {
|
||||
return fmt.Errorf("Failed to set config for supported subsystems : %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *cgroupManagerImpl) toResources(resourceConfig *ResourceConfig) *libcontainerconfigs.Resources {
|
||||
resources := &libcontainerconfigs.Resources{}
|
||||
if resourceConfig == nil {
|
||||
return resources
|
||||
}
|
||||
if resourceConfig.Memory != nil {
|
||||
resources.Memory = *resourceConfig.Memory
|
||||
}
|
||||
if resourceConfig.CpuShares != nil {
|
||||
resources.CpuShares = *resourceConfig.CpuShares
|
||||
}
|
||||
if resourceConfig.CpuQuota != nil {
|
||||
resources.CpuQuota = *resourceConfig.CpuQuota
|
||||
}
|
||||
if resourceConfig.CpuPeriod != nil {
|
||||
resources.CpuPeriod = *resourceConfig.CpuPeriod
|
||||
}
|
||||
return resources
|
||||
}
|
||||
|
||||
// Update updates the cgroup with the specified Cgroup Configuration
|
||||
func (m *cgroupManagerImpl) Update(cgroupConfig *CgroupConfig) error {
|
||||
// Extract the cgroup resource parameters
|
||||
resourceConfig := cgroupConfig.ResourceParameters
|
||||
resources := m.toResources(resourceConfig)
|
||||
|
||||
cgroupPaths := m.buildCgroupPaths(cgroupConfig.Name)
|
||||
|
||||
// we take the location in traditional cgroupfs format.
|
||||
abstractCgroupFsName := string(cgroupConfig.Name)
|
||||
abstractParent := CgroupName(path.Dir(abstractCgroupFsName))
|
||||
abstractName := CgroupName(path.Base(abstractCgroupFsName))
|
||||
|
||||
driverParent := m.adapter.adaptName(abstractParent, false)
|
||||
driverName := m.adapter.adaptName(abstractName, false)
|
||||
|
||||
// this is an ugly abstraction bleed, but systemd cgroup driver requires full paths...
|
||||
if m.adapter.cgroupManagerType == libcontainerSystemd {
|
||||
driverName = m.adapter.adaptName(cgroupConfig.Name, false)
|
||||
}
|
||||
|
||||
// Initialize libcontainer's cgroup config
|
||||
libcontainerCgroupConfig := &libcontainerconfigs.Cgroup{
|
||||
Name: driverName,
|
||||
Parent: driverParent,
|
||||
Resources: resources,
|
||||
Paths: cgroupPaths,
|
||||
}
|
||||
|
||||
if err := setSupportedSubsytems(libcontainerCgroupConfig); err != nil {
|
||||
return fmt.Errorf("failed to set supported cgroup subsystems for cgroup %v: %v", cgroupConfig.Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create creates the specified cgroup
|
||||
func (m *cgroupManagerImpl) Create(cgroupConfig *CgroupConfig) error {
|
||||
|
||||
// we take the location in traditional cgroupfs format.
|
||||
abstractCgroupFsName := string(cgroupConfig.Name)
|
||||
abstractParent := CgroupName(path.Dir(abstractCgroupFsName))
|
||||
abstractName := CgroupName(path.Base(abstractCgroupFsName))
|
||||
|
||||
driverParent := m.adapter.adaptName(abstractParent, false)
|
||||
driverName := m.adapter.adaptName(abstractName, false)
|
||||
// this is an ugly abstraction bleed, but systemd cgroup driver requires full paths...
|
||||
if m.adapter.cgroupManagerType == libcontainerSystemd {
|
||||
driverName = m.adapter.adaptName(cgroupConfig.Name, false)
|
||||
}
|
||||
|
||||
resources := m.toResources(cgroupConfig.ResourceParameters)
|
||||
// Initialize libcontainer's cgroup config with driver specific naming.
|
||||
libcontainerCgroupConfig := &libcontainerconfigs.Cgroup{
|
||||
Name: driverName,
|
||||
Parent: driverParent,
|
||||
Resources: resources,
|
||||
}
|
||||
|
||||
// get the manager with the specified cgroup configuration
|
||||
manager, err := m.adapter.newManager(libcontainerCgroupConfig, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Apply(-1) 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 := manager.Apply(-1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// it may confuse why we call set after we do apply, but the issue is that runc
|
||||
// follows a similar pattern. it's needed to ensure cpu quota is set properly.
|
||||
m.Update(cgroupConfig)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Scans through all subsytems to find pids associated with specified cgroup.
|
||||
func (m *cgroupManagerImpl) Pids(name CgroupName) []int {
|
||||
// we need the driver specific name
|
||||
cgroupFsName := m.Name(name)
|
||||
|
||||
// Get a list of processes that we need to kill
|
||||
pidsToKill := sets.NewInt()
|
||||
var pids []int
|
||||
for _, val := range m.subsystems.MountPoints {
|
||||
dir := path.Join(val, cgroupFsName)
|
||||
_, err := os.Stat(dir)
|
||||
if os.IsNotExist(err) {
|
||||
// The subsystem pod cgroup is already deleted
|
||||
// do nothing, continue
|
||||
continue
|
||||
}
|
||||
// Get a list of pids that are still charged to the pod's cgroup
|
||||
pids, err = getCgroupProcs(dir)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
pidsToKill.Insert(pids...)
|
||||
|
||||
// WalkFunc which is called for each file and directory in the pod cgroup dir
|
||||
visitor := func(path string, info os.FileInfo, err error) error {
|
||||
if !info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
pids, err = getCgroupProcs(path)
|
||||
if err != nil {
|
||||
glog.V(5).Infof("cgroup manager encountered error getting procs for cgroup path %v", path)
|
||||
return filepath.SkipDir
|
||||
}
|
||||
pidsToKill.Insert(pids...)
|
||||
return nil
|
||||
}
|
||||
// Walk through the pod cgroup directory to check if
|
||||
// container cgroups haven't been GCed yet. Get attached processes to
|
||||
// all such unwanted containers under the pod cgroup
|
||||
if err = filepath.Walk(dir, visitor); err != nil {
|
||||
glog.V(5).Infof("cgroup manager encountered error scanning pids for directory: %v", dir)
|
||||
}
|
||||
}
|
||||
return pidsToKill.List()
|
||||
}
|
||||
|
||||
// ReduceCPULimits reduces the cgroup's cpu shares to the lowest possible value
|
||||
func (m *cgroupManagerImpl) ReduceCPULimits(cgroupName CgroupName) error {
|
||||
// Set lowest possible CpuShares value for the cgroup
|
||||
minimumCPUShares := int64(MinShares)
|
||||
resources := &ResourceConfig{
|
||||
CpuShares: &minimumCPUShares,
|
||||
}
|
||||
containerConfig := &CgroupConfig{
|
||||
Name: cgroupName,
|
||||
ResourceParameters: resources,
|
||||
}
|
||||
return m.Update(containerConfig)
|
||||
}
|
||||
81
vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux_test.go
generated
vendored
Normal file
81
vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_linux_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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 "testing"
|
||||
|
||||
func TestLibcontainerAdapterAdaptToSystemd(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
input: "/",
|
||||
expected: "-.slice",
|
||||
},
|
||||
{
|
||||
input: "/Burstable",
|
||||
expected: "Burstable.slice",
|
||||
},
|
||||
{
|
||||
input: "/Burstable/pod_123",
|
||||
expected: "Burstable-pod_123.slice",
|
||||
},
|
||||
{
|
||||
input: "/BestEffort/pod_6c1a4e95-6bb6-11e6-bc26-28d2444e470d",
|
||||
expected: "BestEffort-pod_6c1a4e95_6bb6_11e6_bc26_28d2444e470d.slice",
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
f := newLibcontainerAdapter(libcontainerSystemd)
|
||||
if actual := f.adaptName(CgroupName(testCase.input), false); actual != testCase.expected {
|
||||
t.Errorf("Unexpected result, input: %v, expected: %v, actual: %v", testCase.input, testCase.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLibcontainerAdapterAdaptToSystemdAsCgroupFs(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
input: "/",
|
||||
expected: "/",
|
||||
},
|
||||
{
|
||||
input: "/Burstable",
|
||||
expected: "Burstable.slice/",
|
||||
},
|
||||
{
|
||||
input: "/Burstable/pod_123",
|
||||
expected: "Burstable.slice/Burstable-pod_123.slice/",
|
||||
},
|
||||
{
|
||||
input: "/BestEffort/pod_6c1a4e95-6bb6-11e6-bc26-28d2444e470d",
|
||||
expected: "BestEffort.slice/BestEffort-pod_6c1a4e95_6bb6_11e6_bc26_28d2444e470d.slice/",
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
f := newLibcontainerAdapter(libcontainerSystemd)
|
||||
if actual := f.adaptName(CgroupName(testCase.input), true); actual != testCase.expected {
|
||||
t.Errorf("Unexpected result, input: %v, expected: %v, actual: %v", testCase.input, testCase.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
75
vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_unsupported.go
generated
vendored
Normal file
75
vendor/k8s.io/kubernetes/pkg/kubelet/cm/cgroup_manager_unsupported.go
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
// +build !linux
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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{}
|
||||
|
||||
type CgroupSubsystems struct {
|
||||
Mounts []interface{}
|
||||
MountPoints map[string]string
|
||||
}
|
||||
|
||||
func NewCgroupManager(_ interface{}) CgroupManager {
|
||||
return &unsupportedCgroupManager{}
|
||||
}
|
||||
|
||||
func (m *unsupportedCgroupManager) Name(_ CgroupName) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *unsupportedCgroupManager) Exists(_ CgroupName) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
func (m *unsupportedCgroupManager) Pids(_ CgroupName) []int {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *unsupportedCgroupManager) CgroupName(name string) CgroupName {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *unsupportedCgroupManager) ReduceCPULimits(cgroupName CgroupName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ConvertCgroupFsNameToSystemd(cgroupfsName string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func ConvertCgroupNameToSystemd(cgroupName CgroupName, outputToCgroupFs bool) string {
|
||||
return ""
|
||||
}
|
||||
64
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager.go
generated
vendored
Normal file
64
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager.go
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 "k8s.io/kubernetes/pkg/api/v1"
|
||||
|
||||
// Manages the containers running on a machine.
|
||||
type ContainerManager interface {
|
||||
// Runs the container manager's housekeeping.
|
||||
// - Ensures that the Docker daemon is in a container.
|
||||
// - Creates the system container where all non-containerized processes run.
|
||||
Start(*v1.Node) error
|
||||
|
||||
// Returns resources allocated to system cgroups in the machine.
|
||||
// These cgroups include the system and Kubernetes services.
|
||||
SystemCgroupsLimit() v1.ResourceList
|
||||
|
||||
// Returns a NodeConfig that is being used by the container manager.
|
||||
GetNodeConfig() NodeConfig
|
||||
|
||||
// Returns internal Status.
|
||||
Status() Status
|
||||
|
||||
// NewPodContainerManager is a factory method which returns a podContainerManager object
|
||||
// Returns a noop implementation if qos cgroup hierarchy is not enabled
|
||||
NewPodContainerManager() PodContainerManager
|
||||
|
||||
// GetMountedSubsystems returns the mounted cgroup subsytems on the node
|
||||
GetMountedSubsystems() *CgroupSubsystems
|
||||
|
||||
// GetQOSContainersInfo returns the names of top level QoS containers
|
||||
GetQOSContainersInfo() QOSContainersInfo
|
||||
}
|
||||
|
||||
type NodeConfig struct {
|
||||
RuntimeCgroupsName string
|
||||
SystemCgroupsName string
|
||||
KubeletCgroupsName string
|
||||
ContainerRuntime string
|
||||
CgroupsPerQOS bool
|
||||
CgroupRoot string
|
||||
CgroupDriver string
|
||||
ProtectKernelDefaults bool
|
||||
EnableCRI bool
|
||||
}
|
||||
|
||||
type Status struct {
|
||||
// Any soft requirements that were unsatisfied.
|
||||
SoftRequirements error
|
||||
}
|
||||
813
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux.go
generated
vendored
Normal file
813
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
180
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux_test.go
generated
vendored
Normal file
180
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_linux_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
)
|
||||
|
||||
type fakeMountInterface struct {
|
||||
mountPoints []mount.MountPoint
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) Mount(source string, target string, fstype string, options []string) error {
|
||||
return fmt.Errorf("unsupported")
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) Unmount(target string) error {
|
||||
return fmt.Errorf("unsupported")
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) List() ([]mount.MountPoint, error) {
|
||||
return mi.mountPoints, nil
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return false, fmt.Errorf("unsupported")
|
||||
}
|
||||
func (mi *fakeMountInterface) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) DeviceOpened(pathname string) (bool, error) {
|
||||
for _, mp := range mi.mountPoints {
|
||||
if mp.Device == pathname {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) PathIsDevice(pathname string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func fakeContainerMgrMountInt() mount.Interface {
|
||||
return &fakeMountInterface{
|
||||
[]mount.MountPoint{
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpuset"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpu"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpuacct"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "memory"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestCgroupMountValidationSuccess(t *testing.T) {
|
||||
f, err := validateSystemRequirements(fakeContainerMgrMountInt())
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, f.cpuHardcapping, "cpu hardcapping is expected to be disabled")
|
||||
}
|
||||
|
||||
func TestCgroupMountValidationMemoryMissing(t *testing.T) {
|
||||
mountInt := &fakeMountInterface{
|
||||
[]mount.MountPoint{
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpuset"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpu"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpuacct"},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := validateSystemRequirements(mountInt)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestCgroupMountValidationMultipleSubsytem(t *testing.T) {
|
||||
mountInt := &fakeMountInterface{
|
||||
[]mount.MountPoint{
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpuset", "memory"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpu"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpuacct"},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := validateSystemRequirements(mountInt)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestSoftRequirementsValidationSuccess(t *testing.T) {
|
||||
req := require.New(t)
|
||||
tempDir, err := ioutil.TempDir("", "")
|
||||
req.NoError(err)
|
||||
req.NoError(ioutil.WriteFile(path.Join(tempDir, "cpu.cfs_period_us"), []byte("0"), os.ModePerm))
|
||||
req.NoError(ioutil.WriteFile(path.Join(tempDir, "cpu.cfs_quota_us"), []byte("0"), os.ModePerm))
|
||||
mountInt := &fakeMountInterface{
|
||||
[]mount.MountPoint{
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpuset"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpu"},
|
||||
Path: tempDir,
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpuacct", "memory"},
|
||||
},
|
||||
},
|
||||
}
|
||||
f, err := validateSystemRequirements(mountInt)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, f.cpuHardcapping, "cpu hardcapping is expected to be enabled")
|
||||
}
|
||||
59
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_stub.go
generated
vendored
Normal file
59
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_stub.go
generated
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
type containerManagerStub struct{}
|
||||
|
||||
var _ ContainerManager = &containerManagerStub{}
|
||||
|
||||
func (cm *containerManagerStub) Start(_ *v1.Node) error {
|
||||
glog.V(2).Infof("Starting stub container manager")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cm *containerManagerStub) SystemCgroupsLimit() v1.ResourceList {
|
||||
return v1.ResourceList{}
|
||||
}
|
||||
|
||||
func (cm *containerManagerStub) GetNodeConfig() NodeConfig {
|
||||
return NodeConfig{}
|
||||
}
|
||||
|
||||
func (cm *containerManagerStub) GetMountedSubsystems() *CgroupSubsystems {
|
||||
return &CgroupSubsystems{}
|
||||
}
|
||||
|
||||
func (cm *containerManagerStub) GetQOSContainersInfo() QOSContainersInfo {
|
||||
return QOSContainersInfo{}
|
||||
}
|
||||
|
||||
func (cm *containerManagerStub) Status() Status {
|
||||
return Status{}
|
||||
}
|
||||
|
||||
func (cm *containerManagerStub) NewPodContainerManager() PodContainerManager {
|
||||
return &podContainerManagerStub{}
|
||||
}
|
||||
|
||||
func NewStubContainerManager() ContainerManager {
|
||||
return &containerManagerStub{}
|
||||
}
|
||||
64
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_unsupported.go
generated
vendored
Normal file
64
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_unsupported.go
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// +build !linux,!windows
|
||||
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cadvisor"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
)
|
||||
|
||||
type unsupportedContainerManager struct {
|
||||
}
|
||||
|
||||
var _ ContainerManager = &unsupportedContainerManager{}
|
||||
|
||||
func (unsupportedContainerManager) Start(_ *v1.Node) error {
|
||||
return fmt.Errorf("Container Manager is unsupported in this build")
|
||||
}
|
||||
|
||||
func (unsupportedContainerManager) SystemCgroupsLimit() v1.ResourceList {
|
||||
return v1.ResourceList{}
|
||||
}
|
||||
|
||||
func (unsupportedContainerManager) GetNodeConfig() NodeConfig {
|
||||
return NodeConfig{}
|
||||
}
|
||||
|
||||
func (unsupportedContainerManager) GetMountedSubsystems() *CgroupSubsystems {
|
||||
return &CgroupSubsystems{}
|
||||
}
|
||||
|
||||
func (unsupportedContainerManager) GetQOSContainersInfo() QOSContainersInfo {
|
||||
return QOSContainersInfo{}
|
||||
}
|
||||
|
||||
func (cm *unsupportedContainerManager) Status() Status {
|
||||
return Status{}
|
||||
}
|
||||
|
||||
func (cm *unsupportedContainerManager) NewPodContainerManager() PodContainerManager {
|
||||
return &unsupportedPodContainerManager{}
|
||||
}
|
||||
|
||||
func NewContainerManager(_ mount.Interface, _ cadvisor.Interface, _ NodeConfig, failSwapOn bool) (ContainerManager, error) {
|
||||
return &unsupportedContainerManager{}, nil
|
||||
}
|
||||
89
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_unsupported_test.go
generated
vendored
Normal file
89
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_unsupported_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
// +build !linux,!windows
|
||||
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
)
|
||||
|
||||
type fakeMountInterface struct {
|
||||
mountPoints []mount.MountPoint
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) Mount(source string, target string, fstype string, options []string) error {
|
||||
return fmt.Errorf("unsupported")
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) Unmount(target string) error {
|
||||
return fmt.Errorf("unsupported")
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) List() ([]mount.MountPoint, error) {
|
||||
return mi.mountPoints, nil
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return false, fmt.Errorf("unsupported")
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) DeviceOpened(pathname string) (bool, error) {
|
||||
for _, mp := range mi.mountPoints {
|
||||
if mp.Device == pathname {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) PathIsDevice(pathname string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func fakeContainerMgrMountInt() mount.Interface {
|
||||
return &fakeMountInterface{
|
||||
[]mount.MountPoint{
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpuset"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpu"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "cpuacct"},
|
||||
},
|
||||
{
|
||||
Device: "cgroup",
|
||||
Type: "cgroup",
|
||||
Opts: []string{"rw", "relatime", "memory"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
42
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_windows.go
generated
vendored
Normal file
42
vendor/k8s.io/kubernetes/pkg/kubelet/cm/container_manager_windows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cadvisor"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
)
|
||||
|
||||
type containerManagerImpl struct {
|
||||
containerManagerStub
|
||||
}
|
||||
|
||||
var _ ContainerManager = &containerManagerImpl{}
|
||||
|
||||
func (cm *containerManagerImpl) Start(_ *v1.Node) error {
|
||||
glog.V(2).Infof("Starting Windows stub container manager")
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewContainerManager(mountUtil mount.Interface, cadvisorInterface cadvisor.Interface, nodeConfig NodeConfig, failSwapOn bool) (ContainerManager, error) {
|
||||
return &containerManagerImpl{}, nil
|
||||
}
|
||||
184
vendor/k8s.io/kubernetes/pkg/kubelet/cm/helpers_linux.go
generated
vendored
Normal file
184
vendor/k8s.io/kubernetes/pkg/kubelet/cm/helpers_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/qos"
|
||||
)
|
||||
|
||||
const (
|
||||
// Taken from lmctfy https://github.com/google/lmctfy/blob/master/lmctfy/controllers/cpu_controller.cc
|
||||
MinShares = 2
|
||||
SharesPerCPU = 1024
|
||||
MilliCPUToCPU = 1000
|
||||
|
||||
// 100000 is equivalent to 100ms
|
||||
QuotaPeriod = 100000
|
||||
MinQuotaPeriod = 1000
|
||||
)
|
||||
|
||||
// MilliCPUToQuota converts milliCPU to CFS quota and period values.
|
||||
func MilliCPUToQuota(milliCPU int64) (quota int64, period int64) {
|
||||
// CFS quota is measured in two values:
|
||||
// - cfs_period_us=100ms (the amount of time to measure usage across)
|
||||
// - cfs_quota=20ms (the amount of cpu time allowed to be used across a period)
|
||||
// so in the above example, you are limited to 20% of a single CPU
|
||||
// for multi-cpu environments, you just scale equivalent amounts
|
||||
|
||||
if milliCPU == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// we set the period to 100ms by default
|
||||
period = QuotaPeriod
|
||||
|
||||
// we then convert your milliCPU to a value normalized over a period
|
||||
quota = (milliCPU * QuotaPeriod) / MilliCPUToCPU
|
||||
|
||||
// quota needs to be a minimum of 1ms.
|
||||
if quota < MinQuotaPeriod {
|
||||
quota = MinQuotaPeriod
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// MilliCPUToShares converts the milliCPU to CFS shares.
|
||||
func MilliCPUToShares(milliCPU int64) int64 {
|
||||
if milliCPU == 0 {
|
||||
// Docker converts zero milliCPU to unset, which maps to kernel default
|
||||
// for unset: 1024. Return 2 here to really match kernel default for
|
||||
// zero milliCPU.
|
||||
return MinShares
|
||||
}
|
||||
// Conceptually (milliCPU / milliCPUToCPU) * sharesPerCPU, but factored to improve rounding.
|
||||
shares := (milliCPU * SharesPerCPU) / MilliCPUToCPU
|
||||
if shares < MinShares {
|
||||
return MinShares
|
||||
}
|
||||
return shares
|
||||
}
|
||||
|
||||
// ResourceConfigForPod takes the input pod and outputs the cgroup resource config.
|
||||
func ResourceConfigForPod(pod *v1.Pod) *ResourceConfig {
|
||||
// sum requests and limits, track if limits were applied for each resource.
|
||||
cpuRequests := int64(0)
|
||||
cpuLimits := int64(0)
|
||||
memoryLimits := int64(0)
|
||||
memoryLimitsDeclared := true
|
||||
cpuLimitsDeclared := true
|
||||
for _, container := range pod.Spec.Containers {
|
||||
cpuRequests += container.Resources.Requests.Cpu().MilliValue()
|
||||
cpuLimits += container.Resources.Limits.Cpu().MilliValue()
|
||||
if container.Resources.Limits.Cpu().IsZero() {
|
||||
cpuLimitsDeclared = false
|
||||
}
|
||||
memoryLimits += container.Resources.Limits.Memory().Value()
|
||||
if container.Resources.Limits.Memory().IsZero() {
|
||||
memoryLimitsDeclared = false
|
||||
}
|
||||
}
|
||||
|
||||
// convert to CFS values
|
||||
cpuShares := MilliCPUToShares(cpuRequests)
|
||||
cpuQuota, cpuPeriod := MilliCPUToQuota(cpuLimits)
|
||||
|
||||
// determine the qos class
|
||||
qosClass := qos.GetPodQOS(pod)
|
||||
|
||||
// build the result
|
||||
result := &ResourceConfig{}
|
||||
if qosClass == qos.Guaranteed {
|
||||
result.CpuShares = &cpuShares
|
||||
result.CpuQuota = &cpuQuota
|
||||
result.CpuPeriod = &cpuPeriod
|
||||
result.Memory = &memoryLimits
|
||||
} else if qosClass == qos.Burstable {
|
||||
result.CpuShares = &cpuShares
|
||||
if cpuLimitsDeclared {
|
||||
result.CpuQuota = &cpuQuota
|
||||
result.CpuPeriod = &cpuPeriod
|
||||
}
|
||||
if memoryLimitsDeclared {
|
||||
result.Memory = &memoryLimits
|
||||
}
|
||||
} else {
|
||||
shares := int64(MinShares)
|
||||
result.CpuShares = &shares
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GetCgroupSubsystems returns information about the mounted cgroup subsystems
|
||||
func GetCgroupSubsystems() (*CgroupSubsystems, error) {
|
||||
// get all cgroup mounts.
|
||||
allCgroups, err := libcontainercgroups.GetCgroupMounts(true)
|
||||
if err != nil {
|
||||
return &CgroupSubsystems{}, err
|
||||
}
|
||||
if len(allCgroups) == 0 {
|
||||
return &CgroupSubsystems{}, fmt.Errorf("failed to find cgroup mounts")
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// getCgroupProcs takes a cgroup directory name as an argument
|
||||
// reads through the cgroup's procs file and returns a list of tgid's.
|
||||
// It returns an empty list if a procs file doesn't exists
|
||||
func getCgroupProcs(dir string) ([]int, error) {
|
||||
procsFile := filepath.Join(dir, "cgroup.procs")
|
||||
f, err := os.Open(procsFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// The procsFile does not exist, So no pids attached to this directory
|
||||
return []int{}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
s := bufio.NewScanner(f)
|
||||
out := []int{}
|
||||
for s.Scan() {
|
||||
if t := s.Text(); t != "" {
|
||||
pid, err := strconv.Atoi(t)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unexpected line in %v; could not convert to pid: %v", procsFile, err)
|
||||
}
|
||||
out = append(out, pid)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
199
vendor/k8s.io/kubernetes/pkg/kubelet/cm/helpers_linux_test.go
generated
vendored
Normal file
199
vendor/k8s.io/kubernetes/pkg/kubelet/cm/helpers_linux_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
// getResourceList returns a ResourceList with the
|
||||
// specified cpu and memory resource values
|
||||
func getResourceList(cpu, memory string) v1.ResourceList {
|
||||
res := v1.ResourceList{}
|
||||
if cpu != "" {
|
||||
res[v1.ResourceCPU] = resource.MustParse(cpu)
|
||||
}
|
||||
if memory != "" {
|
||||
res[v1.ResourceMemory] = resource.MustParse(memory)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// getResourceRequirements returns a ResourceRequirements object
|
||||
func getResourceRequirements(requests, limits v1.ResourceList) v1.ResourceRequirements {
|
||||
res := v1.ResourceRequirements{}
|
||||
res.Requests = requests
|
||||
res.Limits = limits
|
||||
return res
|
||||
}
|
||||
|
||||
func TestResourceConfigForPod(t *testing.T) {
|
||||
minShares := int64(MinShares)
|
||||
burstableShares := MilliCPUToShares(100)
|
||||
memoryQuantity := resource.MustParse("200Mi")
|
||||
burstableMemory := memoryQuantity.Value()
|
||||
burstablePartialShares := MilliCPUToShares(200)
|
||||
burstableQuota, burstablePeriod := MilliCPUToQuota(200)
|
||||
guaranteedShares := MilliCPUToShares(100)
|
||||
guaranteedQuota, guaranteedPeriod := MilliCPUToQuota(100)
|
||||
memoryQuantity = resource.MustParse("100Mi")
|
||||
guaranteedMemory := memoryQuantity.Value()
|
||||
testCases := map[string]struct {
|
||||
pod *v1.Pod
|
||||
expected *ResourceConfig
|
||||
}{
|
||||
"besteffort": {
|
||||
pod: &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Resources: getResourceRequirements(getResourceList("", ""), getResourceList("", "")),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &ResourceConfig{CpuShares: &minShares},
|
||||
},
|
||||
"burstable-no-limits": {
|
||||
pod: &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Resources: getResourceRequirements(getResourceList("100m", "100Mi"), getResourceList("", "")),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &ResourceConfig{CpuShares: &burstableShares},
|
||||
},
|
||||
"burstable-with-limits": {
|
||||
pod: &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Resources: getResourceRequirements(getResourceList("100m", "100Mi"), getResourceList("200m", "200Mi")),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &ResourceConfig{CpuShares: &burstableShares, CpuQuota: &burstableQuota, CpuPeriod: &burstablePeriod, Memory: &burstableMemory},
|
||||
},
|
||||
"burstable-partial-limits": {
|
||||
pod: &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Resources: getResourceRequirements(getResourceList("100m", "100Mi"), getResourceList("200m", "200Mi")),
|
||||
},
|
||||
{
|
||||
Resources: getResourceRequirements(getResourceList("100m", "100Mi"), getResourceList("", "")),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &ResourceConfig{CpuShares: &burstablePartialShares},
|
||||
},
|
||||
"guaranteed": {
|
||||
pod: &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Resources: getResourceRequirements(getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &ResourceConfig{CpuShares: &guaranteedShares, CpuQuota: &guaranteedQuota, CpuPeriod: &guaranteedPeriod, Memory: &guaranteedMemory},
|
||||
},
|
||||
}
|
||||
for testName, testCase := range testCases {
|
||||
actual := ResourceConfigForPod(testCase.pod)
|
||||
if !reflect.DeepEqual(actual.CpuPeriod, testCase.expected.CpuPeriod) {
|
||||
t.Errorf("unexpected result, test: %v, cpu period not as expected", testName)
|
||||
}
|
||||
if !reflect.DeepEqual(actual.CpuQuota, testCase.expected.CpuQuota) {
|
||||
t.Errorf("unexpected result, test: %v, cpu quota not as expected", testName)
|
||||
}
|
||||
if !reflect.DeepEqual(actual.CpuShares, testCase.expected.CpuShares) {
|
||||
t.Errorf("unexpected result, test: %v, cpu shares not as expected", testName)
|
||||
}
|
||||
if !reflect.DeepEqual(actual.Memory, testCase.expected.Memory) {
|
||||
t.Errorf("unexpected result, test: %v, memory not as expected", testName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMilliCPUToQuota(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input int64
|
||||
quota int64
|
||||
period int64
|
||||
}{
|
||||
{
|
||||
input: int64(0),
|
||||
quota: int64(0),
|
||||
period: int64(0),
|
||||
},
|
||||
{
|
||||
input: int64(5),
|
||||
quota: int64(1000),
|
||||
period: int64(100000),
|
||||
},
|
||||
{
|
||||
input: int64(9),
|
||||
quota: int64(1000),
|
||||
period: int64(100000),
|
||||
},
|
||||
{
|
||||
input: int64(10),
|
||||
quota: int64(1000),
|
||||
period: int64(100000),
|
||||
},
|
||||
{
|
||||
input: int64(200),
|
||||
quota: int64(20000),
|
||||
period: int64(100000),
|
||||
},
|
||||
{
|
||||
input: int64(500),
|
||||
quota: int64(50000),
|
||||
period: int64(100000),
|
||||
},
|
||||
{
|
||||
input: int64(1000),
|
||||
quota: int64(100000),
|
||||
period: int64(100000),
|
||||
},
|
||||
{
|
||||
input: int64(1500),
|
||||
quota: int64(150000),
|
||||
period: int64(100000),
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
quota, period := MilliCPUToQuota(testCase.input)
|
||||
if quota != testCase.quota || period != testCase.period {
|
||||
t.Errorf("Input %v, expected quota %v period %v, but got quota %v period %v", testCase.input, testCase.quota, testCase.period, quota, period)
|
||||
}
|
||||
}
|
||||
}
|
||||
54
vendor/k8s.io/kubernetes/pkg/kubelet/cm/helpers_unsupported.go
generated
vendored
Normal file
54
vendor/k8s.io/kubernetes/pkg/kubelet/cm/helpers_unsupported.go
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// +build !linux
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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 "k8s.io/kubernetes/pkg/api/v1"
|
||||
|
||||
const (
|
||||
MinShares = 0
|
||||
SharesPerCPU = 0
|
||||
MilliCPUToCPU = 0
|
||||
|
||||
QuotaPeriod = 0
|
||||
MinQuotaPeriod = 0
|
||||
)
|
||||
|
||||
// MilliCPUToQuota converts milliCPU to CFS quota and period values.
|
||||
func MilliCPUToQuota(milliCPU int64) (int64, int64) {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// MilliCPUToShares converts the milliCPU to CFS shares.
|
||||
func MilliCPUToShares(milliCPU int64) int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// ResourceConfigForPod takes the input pod and outputs the cgroup resource config.
|
||||
func ResourceConfigForPod(pod *v1.Pod) *ResourceConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCgroupSubsystems returns information about the mounted cgroup subsystems
|
||||
func GetCgroupSubsystems() (*CgroupSubsystems, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getCgroupProcs(dir string) ([]int, error) {
|
||||
return nil, nil
|
||||
}
|
||||
263
vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_linux.go
generated
vendored
Normal file
263
vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/qos"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
utilerrors "k8s.io/kubernetes/pkg/util/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
podCgroupNamePrefix = "pod"
|
||||
)
|
||||
|
||||
// podContainerManagerImpl implements podContainerManager interface.
|
||||
// It is the general implementation which allows pod level container
|
||||
// management if qos Cgroup is enabled.
|
||||
type podContainerManagerImpl struct {
|
||||
// nodeInfo stores information about the node resource capacity
|
||||
nodeInfo *v1.Node
|
||||
// qosContainersInfo hold absolute paths of the top level qos containers
|
||||
qosContainersInfo QOSContainersInfo
|
||||
// Stores the mounted cgroup subsystems
|
||||
subsystems *CgroupSubsystems
|
||||
// cgroupManager is the cgroup Manager Object responsible for managing all
|
||||
// pod cgroups.
|
||||
cgroupManager CgroupManager
|
||||
}
|
||||
|
||||
// Make sure that podContainerManagerImpl implements the PodContainerManager interface
|
||||
var _ PodContainerManager = &podContainerManagerImpl{}
|
||||
|
||||
// applyLimits sets pod cgroup resource limits
|
||||
// It also updates the resource limits on top level qos containers.
|
||||
func (m *podContainerManagerImpl) applyLimits(pod *v1.Pod) error {
|
||||
// This function will house the logic for setting the resource parameters
|
||||
// on the pod container config and updating top level qos container configs
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exists checks if the pod's cgroup already exists
|
||||
func (m *podContainerManagerImpl) Exists(pod *v1.Pod) bool {
|
||||
podContainerName, _ := m.GetPodContainerName(pod)
|
||||
return m.cgroupManager.Exists(podContainerName)
|
||||
}
|
||||
|
||||
// EnsureExists takes a pod as argument and makes sure that
|
||||
// pod cgroup exists if qos cgroup hierarchy flag is enabled.
|
||||
// If the pod level container doesen't already exist it is created.
|
||||
func (m *podContainerManagerImpl) EnsureExists(pod *v1.Pod) error {
|
||||
podContainerName, _ := m.GetPodContainerName(pod)
|
||||
// check if container already exist
|
||||
alreadyExists := m.Exists(pod)
|
||||
if !alreadyExists {
|
||||
// Create the pod container
|
||||
containerConfig := &CgroupConfig{
|
||||
Name: podContainerName,
|
||||
ResourceParameters: ResourceConfigForPod(pod),
|
||||
}
|
||||
if err := m.cgroupManager.Create(containerConfig); err != nil {
|
||||
return fmt.Errorf("failed to create container for %v : %v", podContainerName, err)
|
||||
}
|
||||
}
|
||||
// Apply appropriate resource limits on the pod container
|
||||
// Top level qos containers limits are not updated
|
||||
// until we figure how to maintain the desired state in the kubelet.
|
||||
// Because maintaining the desired state is difficult without checkpointing.
|
||||
if err := m.applyLimits(pod); err != nil {
|
||||
return fmt.Errorf("failed to apply resource limits on container for %v : %v", podContainerName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPodContainerName returns the CgroupName identifer, and its literal cgroupfs form on the host.
|
||||
func (m *podContainerManagerImpl) GetPodContainerName(pod *v1.Pod) (CgroupName, string) {
|
||||
podQOS := qos.GetPodQOS(pod)
|
||||
// Get the parent QOS container name
|
||||
var parentContainer string
|
||||
switch podQOS {
|
||||
case qos.Guaranteed:
|
||||
parentContainer = m.qosContainersInfo.Guaranteed
|
||||
case qos.Burstable:
|
||||
parentContainer = m.qosContainersInfo.Burstable
|
||||
case qos.BestEffort:
|
||||
parentContainer = m.qosContainersInfo.BestEffort
|
||||
}
|
||||
podContainer := podCgroupNamePrefix + string(pod.UID)
|
||||
|
||||
// Get the absolute path of the cgroup
|
||||
cgroupName := (CgroupName)(path.Join(parentContainer, podContainer))
|
||||
// Get the literal cgroupfs name
|
||||
cgroupfsName := m.cgroupManager.Name(cgroupName)
|
||||
|
||||
return cgroupName, cgroupfsName
|
||||
}
|
||||
|
||||
// Scan through the whole cgroup directory and kill all processes either
|
||||
// attached to the pod cgroup or to a container cgroup under the pod cgroup
|
||||
func (m *podContainerManagerImpl) tryKillingCgroupProcesses(podCgroup CgroupName) error {
|
||||
pidsToKill := m.cgroupManager.Pids(podCgroup)
|
||||
// No pids charged to the terminated pod cgroup return
|
||||
if len(pidsToKill) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var errlist []error
|
||||
// os.Kill often errors out,
|
||||
// We try killing all the pids multiple times
|
||||
for i := 0; i < 5; i++ {
|
||||
if i != 0 {
|
||||
glog.V(3).Infof("Attempt %v failed to kill all unwanted process. Retyring", i)
|
||||
}
|
||||
errlist = []error{}
|
||||
for _, pid := range pidsToKill {
|
||||
p, err := os.FindProcess(pid)
|
||||
if err != nil {
|
||||
// Process not running anymore, do nothing
|
||||
continue
|
||||
}
|
||||
glog.V(3).Infof("Attempt to kill process with pid: %v", pid)
|
||||
if err := p.Kill(); err != nil {
|
||||
glog.V(3).Infof("failed to kill process with pid: %v", pid)
|
||||
errlist = append(errlist, err)
|
||||
}
|
||||
}
|
||||
if len(errlist) == 0 {
|
||||
glog.V(3).Infof("successfully killed all unwanted processes.")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return utilerrors.NewAggregate(errlist)
|
||||
}
|
||||
|
||||
// Destroy destroys the pod container cgroup paths
|
||||
func (m *podContainerManagerImpl) Destroy(podCgroup CgroupName) error {
|
||||
// Try killing all the processes attached to the pod cgroup
|
||||
if err := m.tryKillingCgroupProcesses(podCgroup); err != nil {
|
||||
glog.V(3).Infof("failed to kill all the processes attached to the %v cgroups", podCgroup)
|
||||
return fmt.Errorf("failed to kill all the processes attached to the %v cgroups : %v", podCgroup, err)
|
||||
}
|
||||
|
||||
// Now its safe to remove the pod's cgroup
|
||||
containerConfig := &CgroupConfig{
|
||||
Name: podCgroup,
|
||||
ResourceParameters: &ResourceConfig{},
|
||||
}
|
||||
if err := m.cgroupManager.Destroy(containerConfig); err != nil {
|
||||
return fmt.Errorf("failed to delete cgroup paths for %v : %v", podCgroup, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReduceCPULimits reduces the CPU CFS values to the minimum amount of shares.
|
||||
func (m *podContainerManagerImpl) ReduceCPULimits(podCgroup CgroupName) error {
|
||||
return m.cgroupManager.ReduceCPULimits(podCgroup)
|
||||
}
|
||||
|
||||
// GetAllPodsFromCgroups scans through all the subsytems of pod cgroups
|
||||
// Get list of pods whose cgroup still exist on the cgroup mounts
|
||||
func (m *podContainerManagerImpl) GetAllPodsFromCgroups() (map[types.UID]CgroupName, error) {
|
||||
// Map for storing all the found pods on the disk
|
||||
foundPods := make(map[types.UID]CgroupName)
|
||||
qosContainersList := [3]string{m.qosContainersInfo.BestEffort, m.qosContainersInfo.Burstable, m.qosContainersInfo.Guaranteed}
|
||||
// Scan through all the subsystem mounts
|
||||
// and through each QoS cgroup directory for each subsystem mount
|
||||
// If a pod cgroup exists in even a single subsystem mount
|
||||
// we will attempt to delete it
|
||||
for _, val := range m.subsystems.MountPoints {
|
||||
for _, qosContainerName := range qosContainersList {
|
||||
// get the subsystems QoS cgroup absolute name
|
||||
qcConversion := m.cgroupManager.Name(CgroupName(qosContainerName))
|
||||
qc := path.Join(val, qcConversion)
|
||||
dirInfo, err := ioutil.ReadDir(qc)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read the cgroup directory %v : %v", qc, err)
|
||||
}
|
||||
for i := range dirInfo {
|
||||
// note: we do a contains check because on systemd, the literal cgroupfs name will prefix the qos as well.
|
||||
if dirInfo[i].IsDir() && strings.Contains(dirInfo[i].Name(), podCgroupNamePrefix) {
|
||||
// we need to convert the name to an internal identifier
|
||||
internalName := m.cgroupManager.CgroupName(dirInfo[i].Name())
|
||||
// we then split the name on the pod prefix to determine the uid
|
||||
parts := strings.Split(string(internalName), podCgroupNamePrefix)
|
||||
// the uid is missing, so we log the unexpected cgroup not of form pod<uid>
|
||||
if len(parts) != 2 {
|
||||
location := path.Join(qc, dirInfo[i].Name())
|
||||
glog.Errorf("pod cgroup manager ignoring unexpected cgroup %v because it is not a pod", location)
|
||||
continue
|
||||
}
|
||||
podUID := parts[1]
|
||||
// because the literal cgroupfs name could encode the qos tier (on systemd), we avoid double encoding
|
||||
// by just rebuilding the fully qualified CgroupName according to our internal convention.
|
||||
cgroupName := CgroupName(path.Join(qosContainerName, podCgroupNamePrefix+podUID))
|
||||
foundPods[types.UID(podUID)] = cgroupName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return foundPods, nil
|
||||
}
|
||||
|
||||
// podContainerManagerNoop implements podContainerManager interface.
|
||||
// It is a no-op implementation and basically does nothing
|
||||
// podContainerManagerNoop is used in case the QoS cgroup Hierarchy is not
|
||||
// enabled, so Exists() returns true always as the cgroupRoot
|
||||
// is expected to always exist.
|
||||
type podContainerManagerNoop struct {
|
||||
cgroupRoot CgroupName
|
||||
}
|
||||
|
||||
// Make sure that podContainerManagerStub implements the PodContainerManager interface
|
||||
var _ PodContainerManager = &podContainerManagerNoop{}
|
||||
|
||||
func (m *podContainerManagerNoop) Exists(_ *v1.Pod) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *podContainerManagerNoop) EnsureExists(_ *v1.Pod) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *podContainerManagerNoop) GetPodContainerName(_ *v1.Pod) (CgroupName, string) {
|
||||
return m.cgroupRoot, string(m.cgroupRoot)
|
||||
}
|
||||
|
||||
func (m *podContainerManagerNoop) GetPodContainerNameForDriver(_ *v1.Pod) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Destroy destroys the pod container cgroup paths
|
||||
func (m *podContainerManagerNoop) Destroy(_ CgroupName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *podContainerManagerNoop) ReduceCPULimits(_ CgroupName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *podContainerManagerNoop) GetAllPodsFromCgroups() (map[types.UID]CgroupName, error) {
|
||||
return nil, nil
|
||||
}
|
||||
51
vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_stub.go
generated
vendored
Normal file
51
vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_stub.go
generated
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
)
|
||||
|
||||
type podContainerManagerStub struct {
|
||||
}
|
||||
|
||||
var _ PodContainerManager = &podContainerManagerStub{}
|
||||
|
||||
func (m *podContainerManagerStub) Exists(_ *v1.Pod) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *podContainerManagerStub) EnsureExists(_ *v1.Pod) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *podContainerManagerStub) GetPodContainerName(_ *v1.Pod) (CgroupName, string) {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func (m *podContainerManagerStub) Destroy(_ CgroupName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *podContainerManagerStub) ReduceCPULimits(_ CgroupName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *podContainerManagerStub) GetAllPodsFromCgroups() (map[types.UID]CgroupName, error) {
|
||||
return nil, nil
|
||||
}
|
||||
53
vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_unsupported.go
generated
vendored
Normal file
53
vendor/k8s.io/kubernetes/pkg/kubelet/cm/pod_container_manager_unsupported.go
generated
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
// +build !linux
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
)
|
||||
|
||||
type unsupportedPodContainerManager struct {
|
||||
}
|
||||
|
||||
var _ PodContainerManager = &unsupportedPodContainerManager{}
|
||||
|
||||
func (m *unsupportedPodContainerManager) Exists(_ *v1.Pod) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *unsupportedPodContainerManager) EnsureExists(_ *v1.Pod) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *unsupportedPodContainerManager) GetPodContainerName(_ *v1.Pod) (CgroupName, string) {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func (m *unsupportedPodContainerManager) ReduceCPULimits(_ CgroupName) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *unsupportedPodContainerManager) GetAllPodsFromCgroups() (map[types.UID]CgroupName, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *unsupportedPodContainerManager) Destroy(name CgroupName) error {
|
||||
return nil
|
||||
}
|
||||
107
vendor/k8s.io/kubernetes/pkg/kubelet/cm/types.go
generated
vendored
Normal file
107
vendor/k8s.io/kubernetes/pkg/kubelet/cm/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
)
|
||||
|
||||
// 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
|
||||
// CPU quota period.
|
||||
CpuPeriod *int64
|
||||
}
|
||||
|
||||
// CgroupName is the abstract name of a cgroup prior to any driver specific conversion.
|
||||
type CgroupName string
|
||||
|
||||
// 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 {
|
||||
// Fully qualified name prior to any driver specific conversions.
|
||||
Name CgroupName
|
||||
// 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
|
||||
// Destroy the cgroup.
|
||||
Destroy(*CgroupConfig) error
|
||||
// Update cgroup configuration.
|
||||
Update(*CgroupConfig) error
|
||||
// Exists checks if the cgroup already exists
|
||||
Exists(name CgroupName) bool
|
||||
// Name returns the literal cgroupfs name on the host after any driver specific conversions.
|
||||
// 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
|
||||
Name(name CgroupName) string
|
||||
// CgroupName converts the literal cgroupfs name on the host to an internal identifier.
|
||||
CgroupName(name string) CgroupName
|
||||
// Pids scans through all subsytems to find pids associated with specified cgroup.
|
||||
Pids(name CgroupName) []int
|
||||
// ReduceCPULimits reduces the CPU CFS values to the minimum amount of shares.
|
||||
ReduceCPULimits(cgroupName CgroupName) error
|
||||
}
|
||||
|
||||
// QOSContainersInfo stores the names of containers per qos
|
||||
type QOSContainersInfo struct {
|
||||
Guaranteed string
|
||||
BestEffort string
|
||||
Burstable string
|
||||
}
|
||||
|
||||
// PodContainerManager stores and manages pod level containers
|
||||
// The Pod workers interact with the PodContainerManager to create and destroy
|
||||
// containers for the pod.
|
||||
type PodContainerManager interface {
|
||||
// GetPodContainerName returns the CgroupName identifer, and its literal cgroupfs form on the host.
|
||||
GetPodContainerName(*v1.Pod) (CgroupName, string)
|
||||
|
||||
// EnsureExists takes a pod as argument and makes sure that
|
||||
// pod cgroup exists if qos cgroup hierarchy flag is enabled.
|
||||
// If the pod cgroup doesen't already exist this method creates it.
|
||||
EnsureExists(*v1.Pod) error
|
||||
|
||||
// Exists returns true if the pod cgroup exists.
|
||||
Exists(*v1.Pod) bool
|
||||
|
||||
// Destroy takes a pod Cgroup name as argument and destroys the pod's container.
|
||||
Destroy(name CgroupName) error
|
||||
|
||||
// ReduceCPULimits reduces the CPU CFS values to the minimum amount of shares.
|
||||
ReduceCPULimits(name CgroupName) error
|
||||
|
||||
// GetAllPodsFromCgroups enumerates the set of pod uids to their associated cgroup based on state of cgroupfs system.
|
||||
GetAllPodsFromCgroups() (map[types.UID]CgroupName, error)
|
||||
}
|
||||
21
vendor/k8s.io/kubernetes/pkg/kubelet/cm/util/BUILD
generated
vendored
Normal file
21
vendor/k8s.io/kubernetes/pkg/kubelet/cm/util/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["cgroups_linux.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor:github.com/opencontainers/runc/libcontainer/cgroups",
|
||||
"//vendor:github.com/opencontainers/runc/libcontainer/utils",
|
||||
],
|
||||
)
|
||||
76
vendor/k8s.io/kubernetes/pkg/kubelet/cm/util/cgroups_linux.go
generated
vendored
Normal file
76
vendor/k8s.io/kubernetes/pkg/kubelet/cm/util/cgroups_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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 util
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
libcontainerutils "github.com/opencontainers/runc/libcontainer/utils"
|
||||
)
|
||||
|
||||
// Forked from opencontainers/runc/libcontainer/cgroup/fs.Manager.GetPids()
|
||||
func GetPids(cgroupPath string) ([]int, error) {
|
||||
dir, err := getCgroupPath(cgroupPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return libcontainercgroups.GetPids(dir)
|
||||
}
|
||||
|
||||
// getCgroupPath gets the file path to the "devices" subsystem of the desired cgroup.
|
||||
// cgroupPath is the path in the cgroup hierarchy.
|
||||
func getCgroupPath(cgroupPath string) (string, error) {
|
||||
cgroupPath = libcontainerutils.CleanPath(cgroupPath)
|
||||
|
||||
mnt, root, err := libcontainercgroups.FindCgroupMountpointAndRoot("devices")
|
||||
// If we didn't mount the subsystem, there is no point we make the path.
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
|
||||
if filepath.IsAbs(cgroupPath) {
|
||||
// Sometimes subsystems can be mounted togethger as 'cpu,cpuacct'.
|
||||
return filepath.Join(root, mnt, cgroupPath), nil
|
||||
}
|
||||
|
||||
parentPath, err := getCgroupParentPath(mnt, root)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return filepath.Join(parentPath, cgroupPath), nil
|
||||
}
|
||||
|
||||
// getCgroupParentPath gets the parent filepath to this cgroup, for resolving relative cgroup paths.
|
||||
func getCgroupParentPath(mountpoint, root string) (string, error) {
|
||||
// Use GetThisCgroupDir instead of GetInitCgroupDir, because the creating
|
||||
// process could in container and shared pid namespace with host, and
|
||||
// /proc/1/cgroup could point to whole other world of cgroups.
|
||||
initPath, err := libcontainercgroups.GetThisCgroupDir("devices")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// This is needed for nested containers, because in /proc/self/cgroup we
|
||||
// see paths from host, which don't exist in container.
|
||||
relDir, err := filepath.Rel(root, initPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(mountpoint, relDir), nil
|
||||
}
|
||||
23
vendor/k8s.io/kubernetes/pkg/kubelet/cm/util/cgroups_unsupported.go
generated
vendored
Normal file
23
vendor/k8s.io/kubernetes/pkg/kubelet/cm/util/cgroups_unsupported.go
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// +build !linux
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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 util
|
||||
|
||||
func GetPids(cgroupPath string) ([]int, error) {
|
||||
return nil, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue