Commit e397cb4e authored by Akihiro Suda's avatar Akihiro Suda Committed by Darren Shepherd

kubelet/cm: ignore cgroups error when running in userns

This is a hacky POC; we need to implement rootless PCM in the proper way. Especially, pcm.Exists(existingPodName) needs to be implemented to return true even when cgroups is not available. Signed-off-by: 's avatarAkihiro Suda <suda.akihiro@lab.ntt.co.jp>
parent 446dd3ff
...@@ -145,6 +145,7 @@ go_library( ...@@ -145,6 +145,7 @@ go_library(
"//vendor/github.com/google/cadvisor/events:go_default_library", "//vendor/github.com/google/cadvisor/events:go_default_library",
"//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/google/cadvisor/info/v2:go_default_library", "//vendor/github.com/google/cadvisor/info/v2:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/system:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/integer:go_default_library", "//vendor/k8s.io/utils/integer:go_default_library",
......
...@@ -29,6 +29,7 @@ import ( ...@@ -29,6 +29,7 @@ import (
cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs" cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
cgroupsystemd "github.com/opencontainers/runc/libcontainer/cgroups/systemd" cgroupsystemd "github.com/opencontainers/runc/libcontainer/cgroups/systemd"
libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs" libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
rsystem "github.com/opencontainers/runc/libcontainer/system"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
...@@ -148,8 +149,9 @@ func (l *libcontainerAdapter) newManager(cgroups *libcontainerconfigs.Cgroup, pa ...@@ -148,8 +149,9 @@ func (l *libcontainerAdapter) newManager(cgroups *libcontainerconfigs.Cgroup, pa
switch l.cgroupManagerType { switch l.cgroupManagerType {
case libcontainerCgroupfs: case libcontainerCgroupfs:
return &cgroupfs.Manager{ return &cgroupfs.Manager{
Cgroups: cgroups, Cgroups: cgroups,
Paths: paths, Rootless: rsystem.RunningInUserNS(),
Paths: paths,
}, nil }, nil
case libcontainerSystemd: case libcontainerSystemd:
// this means you asked systemd to manage cgroups, but systemd was not on the host, so all you can do is panic... // this means you asked systemd to manage cgroups, but systemd was not on the host, so all you can do is panic...
...@@ -482,7 +484,9 @@ func (m *cgroupManagerImpl) Create(cgroupConfig *CgroupConfig) error { ...@@ -482,7 +484,9 @@ func (m *cgroupManagerImpl) Create(cgroupConfig *CgroupConfig) error {
// in the tasks file. We use the function to create all the required // in the tasks file. We use the function to create all the required
// cgroup files but not attach any "real" pid to the cgroup. // cgroup files but not attach any "real" pid to the cgroup.
if err := manager.Apply(-1); err != nil { if err := manager.Apply(-1); err != nil {
return err if !rsystem.RunningInUserNS() {
return err
}
} }
// it may confuse why we call set after we do apply, but the issue is that runc // it may confuse why we call set after we do apply, but the issue is that runc
......
...@@ -481,13 +481,20 @@ func (cm *containerManagerImpl) setupNode(activePods ActivePodsFunc) error { ...@@ -481,13 +481,20 @@ func (cm *containerManagerImpl) setupNode(activePods ActivePodsFunc) error {
}, },
} }
cont.ensureStateFunc = func(_ *fs.Manager) error { cont.ensureStateFunc = func(_ *fs.Manager) error {
return ensureProcessInContainerWithOOMScore(os.Getpid(), qos.KubeletOOMScoreAdj, &manager) err := ensureProcessInContainerWithOOMScore(os.Getpid(), qos.KubeletOOMScoreAdj, &manager)
if rsystem.RunningInUserNS() {
// if we are in userns, cgroups might not be available
err = nil
}
return err
} }
systemContainers = append(systemContainers, cont) systemContainers = append(systemContainers, cont)
} else { } else {
cm.periodicTasks = append(cm.periodicTasks, func() { cm.periodicTasks = append(cm.periodicTasks, func() {
if err := ensureProcessInContainerWithOOMScore(os.Getpid(), qos.KubeletOOMScoreAdj, nil); err != nil { if err := ensureProcessInContainerWithOOMScore(os.Getpid(), qos.KubeletOOMScoreAdj, nil); err != nil {
klog.Error(err) if !rsystem.RunningInUserNS() {
klog.Error(err)
}
return return
} }
cont, err := getContainer(os.Getpid()) cont, err := getContainer(os.Getpid())
......
...@@ -28,6 +28,7 @@ import ( ...@@ -28,6 +28,7 @@ import (
units "github.com/docker/go-units" units "github.com/docker/go-units"
cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs" cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
rsystem "github.com/opencontainers/runc/libcontainer/system"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/v1/resource" "k8s.io/kubernetes/pkg/api/v1/resource"
...@@ -82,7 +83,9 @@ func (m *qosContainerManagerImpl) Start(getNodeAllocatable func() v1.ResourceLis ...@@ -82,7 +83,9 @@ func (m *qosContainerManagerImpl) Start(getNodeAllocatable func() v1.ResourceLis
cm := m.cgroupManager cm := m.cgroupManager
rootContainer := m.cgroupRoot rootContainer := m.cgroupRoot
if !cm.Exists(rootContainer) { if !cm.Exists(rootContainer) {
return fmt.Errorf("root container %v doesn't exist", rootContainer) if !rsystem.RunningInUserNS() {
return fmt.Errorf("root container %v doesn't exist", rootContainer)
}
} }
// Top level for Qos containers are created only for Burstable // Top level for Qos containers are created only for Burstable
...@@ -323,15 +326,23 @@ func (m *qosContainerManagerImpl) UpdateCgroups() error { ...@@ -323,15 +326,23 @@ func (m *qosContainerManagerImpl) UpdateCgroups() error {
} }
} }
updateSuccess := true
for _, config := range qosConfigs { for _, config := range qosConfigs {
err := m.cgroupManager.Update(config) err := m.cgroupManager.Update(config)
if err != nil { if err != nil {
klog.Errorf("[ContainerManager]: Failed to update QoS cgroup configuration") if rsystem.RunningInUserNS() {
return err // if we are in userns, cgroups might not available
updateSuccess = false
} else {
klog.Errorf("[ContainerManager]: Failed to update QoS cgroup configuration")
return err
}
} }
} }
klog.V(4).Infof("[ContainerManager]: Updated QoS cgroup configuration") if updateSuccess {
klog.V(4).Infof("[ContainerManager]: Updated QoS cgroup configuration")
}
return nil return nil
} }
......
...@@ -36,6 +36,7 @@ go_library( ...@@ -36,6 +36,7 @@ go_library(
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library", "//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/system:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:nacl": [ "@io_bazel_rules_go//go/platform:nacl": [
"//pkg/kubelet/dockershim/libdocker:go_default_library", "//pkg/kubelet/dockershim/libdocker:go_default_library",
......
...@@ -27,6 +27,7 @@ import ( ...@@ -27,6 +27,7 @@ import (
"github.com/opencontainers/runc/libcontainer/cgroups/fs" "github.com/opencontainers/runc/libcontainer/cgroups/fs"
"github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs"
rsystem "github.com/opencontainers/runc/libcontainer/system"
utilversion "k8s.io/apimachinery/pkg/util/version" utilversion "k8s.io/apimachinery/pkg/util/version"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog" "k8s.io/klog"
...@@ -95,7 +96,10 @@ func (m *containerManager) doWork() { ...@@ -95,7 +96,10 @@ func (m *containerManager) doWork() {
// 1. Ensure processes run in the cgroups if m.cgroupsManager is not nil. // 1. Ensure processes run in the cgroups if m.cgroupsManager is not nil.
// 2. Ensure processes have the OOM score applied. // 2. Ensure processes have the OOM score applied.
if err := kubecm.EnsureDockerInContainer(version, dockerOOMScoreAdj, m.cgroupsManager); err != nil { if err := kubecm.EnsureDockerInContainer(version, dockerOOMScoreAdj, m.cgroupsManager); err != nil {
klog.Errorf("Unable to ensure the docker processes run in the desired containers: %v", err) // if we are in userns, the operation is likely to fail, unless cgroupfs is properly chown-ed.
if !rsystem.RunningInUserNS() {
klog.Errorf("Unable to ensure the docker processes run in the desired containers: %v", err)
}
} }
} }
......
...@@ -33,7 +33,8 @@ import ( ...@@ -33,7 +33,8 @@ import (
cadvisorapi "github.com/google/cadvisor/info/v1" cadvisorapi "github.com/google/cadvisor/info/v1"
cadvisorapiv2 "github.com/google/cadvisor/info/v2" cadvisorapiv2 "github.com/google/cadvisor/info/v2"
"k8s.io/api/core/v1" rsystem "github.com/opencontainers/runc/libcontainer/system"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
...@@ -1585,10 +1586,13 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error { ...@@ -1585,10 +1586,13 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error {
break break
} }
} }
// TODO(AkihiroSuda): implement rootless cgroup manager that can emulate Exists() properly
// Don't kill containers in pod if pod's cgroups already // Don't kill containers in pod if pod's cgroups already
// exists or the pod is running for the first time // exists or the pod is running for the first time
podKilled := false podKilled := false
if !pcm.Exists(pod) && !firstSync { if !pcm.Exists(pod) && !firstSync && !rsystem.RunningInUserNS() {
if err := kl.killPod(pod, nil, podStatus, nil); err == nil { if err := kl.killPod(pod, nil, podStatus, nil); err == nil {
podKilled = true podKilled = true
} }
...@@ -1607,7 +1611,9 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error { ...@@ -1607,7 +1611,9 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error {
} }
if err := pcm.EnsureExists(pod); err != nil { if err := pcm.EnsureExists(pod); err != nil {
kl.recorder.Eventf(pod, v1.EventTypeWarning, events.FailedToCreatePodContainer, "unable to ensure pod container exists: %v", err) kl.recorder.Eventf(pod, v1.EventTypeWarning, events.FailedToCreatePodContainer, "unable to ensure pod container exists: %v", err)
return fmt.Errorf("failed to ensure that the pod: %v cgroups exist and are correctly applied: %v", pod.UID, err) if !rsystem.RunningInUserNS() {
return fmt.Errorf("failed to ensure that the pod: %v cgroups exist and are correctly applied: %v", pod.UID, err)
}
} }
} }
} }
......
...@@ -30,6 +30,7 @@ go_library( ...@@ -30,6 +30,7 @@ go_library(
"//vendor/github.com/google/cadvisor/info/v1:go_default_library", "//vendor/github.com/google/cadvisor/info/v1:go_default_library",
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/system:go_default_library",
], ],
) )
......
...@@ -21,7 +21,9 @@ import ( ...@@ -21,7 +21,9 @@ import (
"k8s.io/klog" "k8s.io/klog"
rsystem "github.com/opencontainers/runc/libcontainer/system"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
"k8s.io/kubernetes/pkg/kubelet/util" "k8s.io/kubernetes/pkg/kubelet/util"
) )
...@@ -74,7 +76,13 @@ func (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error) ...@@ -74,7 +76,13 @@ func (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error)
nodeConfig := sp.provider.GetNodeConfig() nodeConfig := sp.provider.GetNodeConfig()
rootStats, networkStats, err := sp.provider.GetCgroupStats("/", updateStats) rootStats, networkStats, err := sp.provider.GetCgroupStats("/", updateStats)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get root cgroup stats: %v", err) if !rsystem.RunningInUserNS() {
return nil, fmt.Errorf("failed to get root cgroup stats: %v", err)
}
// if we are in userns, cgroups might not be available
klog.Errorf("failed to get root cgroup stats: %v", err)
rootStats = &statsapi.ContainerStats{}
networkStats = &statsapi.NetworkStats{}
} }
rootFsStats, err := sp.provider.RootFsStats() rootFsStats, err := sp.provider.RootFsStats()
if err != nil { if err != nil {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment