Tolerate missing HugeTLB cgroups controller

Signed-off-by: Davanum Srinivas <davanum@gmail.com>
This commit is contained in:
Davanum Srinivas
2020-06-01 10:33:20 -04:00
parent 8898550e34
commit d7ce093d63
6 changed files with 100 additions and 13 deletions

View File

@@ -27,6 +27,8 @@ import (
"sort"
"strconv"
"strings"
"sync"
"syscall"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/log"
@@ -36,6 +38,7 @@ import (
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
@@ -405,7 +408,7 @@ func WithSelinuxLabels(process, mount string) oci.SpecOpts {
}
// WithResources sets the provided resource restrictions
func WithResources(resources *runtime.LinuxContainerResources) oci.SpecOpts {
func WithResources(resources *runtime.LinuxContainerResources, tolerateMissingHugePagesCgroupController bool) oci.SpecOpts {
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
if resources == nil {
return nil
@@ -448,16 +451,93 @@ func WithResources(resources *runtime.LinuxContainerResources) oci.SpecOpts {
if limit != 0 {
s.Linux.Resources.Memory.Limit = &limit
}
for _, limit := range hugepages {
s.Linux.Resources.HugepageLimits = append(s.Linux.Resources.HugepageLimits, runtimespec.LinuxHugepageLimit{
Pagesize: limit.PageSize,
Limit: limit.Limit,
})
if isHugePagesControllerPresent() {
for _, limit := range hugepages {
s.Linux.Resources.HugepageLimits = append(s.Linux.Resources.HugepageLimits, runtimespec.LinuxHugepageLimit{
Pagesize: limit.PageSize,
Limit: limit.Limit,
})
}
} else {
if !tolerateMissingHugePagesCgroupController {
return errors.Errorf("huge pages limits are specified but hugetlb cgroup controller is missing. " +
"Please set tolerate_missing_hugepages_controller to `true` to ignore this error")
}
logrus.Warn("hugetlb cgroup controller is absent. skipping huge pages limits")
}
return nil
}
}
var (
supportsHugetlbOnce sync.Once
supportsHugetlb bool
)
func isHugePagesControllerPresent() bool {
supportsHugetlbOnce.Do(func() {
supportsHugetlb = false
if IsCgroup2UnifiedMode() {
supportsHugetlb, _ = cgroupv2HasHugetlb()
} else {
supportsHugetlb, _ = cgroupv1HasHugetlb()
}
})
return supportsHugetlb
}
var (
_cgroupv1HasHugetlbOnce sync.Once
_cgroupv1HasHugetlb bool
_cgroupv1HasHugetlbErr error
_cgroupv2HasHugetlbOnce sync.Once
_cgroupv2HasHugetlb bool
_cgroupv2HasHugetlbErr error
isUnifiedOnce sync.Once
isUnified bool
)
// cgroupv1HasHugetlb returns whether the hugetlb controller is present on
// cgroup v1.
func cgroupv1HasHugetlb() (bool, error) {
_cgroupv1HasHugetlbOnce.Do(func() {
if _, err := ioutil.ReadDir("/sys/fs/cgroup/hugetlb"); err != nil {
_cgroupv1HasHugetlbErr = errors.Wrap(err, "readdir /sys/fs/cgroup/hugetlb")
_cgroupv1HasHugetlb = false
} else {
_cgroupv1HasHugetlbErr = nil
_cgroupv1HasHugetlb = true
}
})
return _cgroupv1HasHugetlb, _cgroupv1HasHugetlbErr
}
// cgroupv2HasHugetlb returns whether the hugetlb controller is present on
// cgroup v2.
func cgroupv2HasHugetlb() (bool, error) {
_cgroupv2HasHugetlbOnce.Do(func() {
controllers, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers")
if err != nil {
_cgroupv2HasHugetlbErr = errors.Wrap(err, "read /sys/fs/cgroup/cgroup.controllers")
return
}
_cgroupv2HasHugetlb = strings.Contains(string(controllers), "hugetlb")
})
return _cgroupv2HasHugetlb, _cgroupv2HasHugetlbErr
}
// IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode.
func IsCgroup2UnifiedMode() bool {
isUnifiedOnce.Do(func() {
var st syscall.Statfs_t
if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil {
panic("cannot statfs cgroup root")
}
isUnified = st.Type == unix.CGROUP2_SUPER_MAGIC
})
return isUnified
}
// WithOOMScoreAdj sets the oom score
func WithOOMScoreAdj(config *runtime.ContainerConfig, restrict bool) oci.SpecOpts {
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error {