Skip to content

Commit f458a74

Browse files
authored
Merge pull request kubernetes#125277 from iholder101/swap/skip_critical_pods
[KEP-2400]: Restrict access to swap for containers in high priority Pods
2 parents 887def0 + a6df16a commit f458a74

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

pkg/kubelet/kuberuntime/kuberuntime_container_linux.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,11 @@ func (m *kubeGenericRuntimeManager) configureContainerSwapResources(lcr *runtime
180180
return
181181
}
182182

183+
if kubelettypes.IsCriticalPod(pod) {
184+
swapConfigurationHelper.ConfigureNoSwap(lcr)
185+
return
186+
}
187+
183188
// NOTE(ehashman): Behavior is defined in the opencontainers runtime spec:
184189
// https://github.com/opencontainers/runtime-spec/blob/1c3f411f041711bbeecf35ff7e93461ea6789220/config-linux.md#memory
185190
switch m.memorySwapBehavior {

pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ import (
4040
utilfeature "k8s.io/apiserver/pkg/util/feature"
4141
featuregatetesting "k8s.io/component-base/featuregate/testing"
4242
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
43+
"k8s.io/kubernetes/pkg/apis/scheduling"
4344
"k8s.io/kubernetes/pkg/features"
4445
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
46+
"k8s.io/utils/ptr"
4547
)
4648

4749
func makeExpectedConfig(m *kubeGenericRuntimeManager, pod *v1.Pod, containerIndex int, enforceMemoryQoS bool) *runtimeapi.ContainerConfig {
@@ -1031,6 +1033,7 @@ func TestGenerateLinuxContainerResourcesWithSwap(t *testing.T) {
10311033
swapBehavior string
10321034
addContainerWithoutRequests bool
10331035
addGuaranteedContainer bool
1036+
isCriticalPod bool
10341037
}{
10351038
// With cgroup v1
10361039
{
@@ -1208,6 +1211,16 @@ func TestGenerateLinuxContainerResourcesWithSwap(t *testing.T) {
12081211
addContainerWithoutRequests: true,
12091212
addGuaranteedContainer: false,
12101213
},
1214+
1215+
// When the pod is considered critical, disallow swap access
1216+
{
1217+
name: "Best-effort QoS, cgroups v2, LimitedSwap, critical pod",
1218+
cgroupVersion: cgroupV2,
1219+
qosClass: v1.PodQOSBurstable,
1220+
nodeSwapFeatureGateEnabled: true,
1221+
swapBehavior: types.LimitedSwap,
1222+
isCriticalPod: true,
1223+
},
12111224
} {
12121225
t.Run(tc.name, func(t *testing.T) {
12131226
setCgroupVersionDuringTest(tc.cgroupVersion)
@@ -1244,6 +1257,11 @@ func TestGenerateLinuxContainerResourcesWithSwap(t *testing.T) {
12441257
pod.Spec.Containers[0].Resources = resourceReqsC1
12451258
pod.Spec.Containers[1].Resources = resourceReqsC2
12461259

1260+
if tc.isCriticalPod {
1261+
pod.Spec.Priority = ptr.To(scheduling.SystemCriticalPriority)
1262+
assert.True(t, types.IsCriticalPod(pod), "pod is expected to be critical")
1263+
}
1264+
12471265
resourcesC1 := m.generateLinuxContainerResources(pod, &pod.Spec.Containers[0], false)
12481266
resourcesC2 := m.generateLinuxContainerResources(pod, &pod.Spec.Containers[1], false)
12491267

@@ -1252,7 +1270,7 @@ func TestGenerateLinuxContainerResourcesWithSwap(t *testing.T) {
12521270
return
12531271
}
12541272

1255-
if !tc.nodeSwapFeatureGateEnabled || tc.cgroupVersion == cgroupV1 || (tc.swapBehavior == types.LimitedSwap && tc.qosClass != v1.PodQOSBurstable) {
1273+
if tc.isCriticalPod || !tc.nodeSwapFeatureGateEnabled || tc.cgroupVersion == cgroupV1 || (tc.swapBehavior == types.LimitedSwap && tc.qosClass != v1.PodQOSBurstable) {
12561274
expectNoSwap(tc.cgroupVersion, resourcesC1, resourcesC2)
12571275
return
12581276
}

test/e2e_node/swap_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ var _ = SIGDescribe("Swap", "[LinuxOnly]", nodefeature.Swap, framework.WithSeria
8484
ginkgo.Entry("QOS Burstable with memory request equals to limit", v1.PodQOSBurstable, true),
8585
ginkgo.Entry("QOS Guaranteed", v1.PodQOSGuaranteed, false),
8686
)
87+
88+
ginkgo.It("with a critical pod - should avoid swap", func() {
89+
ginkgo.By("Creating a critical pod")
90+
const memoryRequestEqualLimit = false
91+
pod := getSwapTestPod(f, v1.PodQOSBurstable, memoryRequestEqualLimit)
92+
pod.Spec.PriorityClassName = "system-node-critical"
93+
94+
pod = runPodAndWaitUntilScheduled(f, pod)
95+
gomega.Expect(types.IsCriticalPod(pod)).To(gomega.BeTrueBecause("pod should be critical"))
96+
97+
ginkgo.By("expecting pod to not have swap access")
98+
expectNoSwap(f, pod)
99+
})
87100
})
88101

89102
f.Context(framework.WithSerial(), func() {

0 commit comments

Comments
 (0)