From 96c2b81670c8a0205c1188b78e131b115c84c03f Mon Sep 17 00:00:00 2001 From: Rodrigo Campos Date: Thu, 13 Feb 2025 13:03:18 +0100 Subject: [PATCH 1/3] features: Enable user namespaces by default The feature gate UserNamespacesSupport is enabled by default now (KEP 127): https://github.com/kubernetes/enhancements/pull/5118. Signed-off-by: Rodrigo Campos --- pkg/features/versioned_kube_features.go | 1 + .../featuregates_linter/test_data/versioned_feature_list.yaml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/pkg/features/versioned_kube_features.go b/pkg/features/versioned_kube_features.go index 79b7ff156a0..e3d19555151 100644 --- a/pkg/features/versioned_kube_features.go +++ b/pkg/features/versioned_kube_features.go @@ -797,6 +797,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate UserNamespacesSupport: { {Version: version.MustParse("1.25"), Default: false, PreRelease: featuregate.Alpha}, {Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Beta}, + {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, }, VolumeAttributesClass: { diff --git a/test/featuregates_linter/test_data/versioned_feature_list.yaml b/test/featuregates_linter/test_data/versioned_feature_list.yaml index df71e5d3a1e..b409c0c9eec 100644 --- a/test/featuregates_linter/test_data/versioned_feature_list.yaml +++ b/test/featuregates_linter/test_data/versioned_feature_list.yaml @@ -1486,6 +1486,10 @@ lockToDefault: false preRelease: Beta version: "1.30" + - default: true + lockToDefault: false + preRelease: Beta + version: "1.33" - name: VolumeAttributesClass versionedSpecs: - default: false From 3725c6f7650c86613bf5cad31e7e946dc6ae099b Mon Sep 17 00:00:00 2001 From: Rodrigo Campos Date: Thu, 13 Feb 2025 14:51:45 +0100 Subject: [PATCH 2/3] pkg/kubelet: Make newTestKubeletWithImageList allocate a userns manager When switching the feature flag to on by default, this test was failing: I0213 14:42:45.311186 341895 factory.go:193] Registered Plugin "containerd" I0213 14:42:45.315673 341895 plugins.go:615] "Loaded volume plugin" pluginName="fake" I0213 14:42:45.315750 341895 kubelet_pods.go:1165] "Clean up pod workers for terminated pods" I0213 14:42:45.315759 341895 kubelet_pods.go:1215] "Clean up probes for terminated pods" I0213 14:42:45.315764 341895 kubelet_pods.go:1219] "Clean up orphaned pod statuses" I0213 14:42:45.315768 341895 kubelet_pods.go:1223] "Clean up orphaned pod user namespace allocations" --- FAIL: TestKubelet_HandlePodCleanups (0.00s) --- FAIL: TestKubelet_HandlePodCleanups/missing_pod_is_requested_for_termination_with_short_grace_period (0.00s) panic: runtime error: invalid memory address or nil pointer dereference [recovered] panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x2b14d7e] goroutine 142 [running]: testing.tRunner.func1.2({0x30b5260, 0x5cfa1e0}) /usr/lib/go-1.23/src/testing/testing.go:1632 +0x230 testing.tRunner.func1() /usr/lib/go-1.23/src/testing/testing.go:1635 +0x35e panic({0x30b5260?, 0x5cfa1e0?}) /usr/lib/go-1.23/src/runtime/panic.go:785 +0x132 k8s.io/kubernetes/pkg/kubelet/userns.(*UsernsManager).CleanupOrphanedPodUsernsAllocations(0x0, {0x5d90f80, 0x0, 0x0?}, {0xc0006a1d50, 0x1, 0x0?}) /home/rodrigo/src/kinvolk/kubernetes/kubernetes/pkg/kubelet/userns/userns_manager.go:474 +0x9e k8s.io/kubernetes/pkg/kubelet.(*Kubelet).HandlePodCleanups(0xc00067c808, {0x3b876b0, 0x5d90f80}) /home/rodrigo/src/kinvolk/kubernetes/kubernetes/pkg/kubelet/kubelet_pods.go:1224 +0x618 k8s.io/kubernetes/pkg/kubelet.TestKubelet_HandlePodCleanups.func35(0xc0001349c0) /home/rodrigo/src/kinvolk/kubernetes/kubernetes/pkg/kubelet/kubelet_pods_test.go:6415 +0x72d testing.tRunner(0xc0001349c0, 0xc0009801b0) /usr/lib/go-1.23/src/testing/testing.go:1690 +0xf4 created by testing.(*T).Run in goroutine 141 /usr/lib/go-1.23/src/testing/testing.go:1743 +0x390 exit status 2 FAIL k8s.io/kubernetes/pkg/kubelet 0.029s The issue is that no userns manager is allocated in the FakeKubelet. Let's allocate one. Signed-off-by: Rodrigo Campos --- pkg/kubelet/kubelet_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 5d8b9d397d8..fd17dd75050 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -95,6 +95,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/sysctl" "k8s.io/kubernetes/pkg/kubelet/token" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" + "k8s.io/kubernetes/pkg/kubelet/userns" kubeletutil "k8s.io/kubernetes/pkg/kubelet/util" "k8s.io/kubernetes/pkg/kubelet/util/queue" kubeletvolume "k8s.io/kubernetes/pkg/kubelet/volumemanager" @@ -368,6 +369,10 @@ func newTestKubeletWithImageList( ShutdownGracePeriodCriticalPods: 0, }) kubelet.shutdownManager = shutdownManager + kubelet.usernsManager, err = userns.MakeUserNsManager(kubelet) + if err != nil { + t.Fatalf("Failed to create UserNsManager: %v", err) + } kubelet.admitHandlers.AddPodAdmitHandler(shutdownManager) // Add this as cleanup predicate pod admitter From 3b7926824ec3733c66476c2228daa5d9253d0e94 Mon Sep 17 00:00:00 2001 From: Rodrigo Campos Date: Thu, 13 Feb 2025 15:32:10 +0100 Subject: [PATCH 3/3] e2e_node: Don't use userns in DefaultPocMount tests When proc mount is set to default, it should mask /proc. The DefaultProcMount test was setting "hostUsers: false" which means to create a user namespaces. This was not causing issues before, because user namespaces was disabled by default and therefore the field was completely ignored. Now that userns is enabled by default, the test is failing as the runtime doesn't always have userns support. One option would be to filter for runtimes that do have userns support. But the default case (/proc is masked) for sure we want to test it without userns support, as it will be applied to all pods. To that end, we add a param "hostUsers bool" to testProcMount that will enable it or not. Then, both test cases that call this function set it accordingly: the default case sets it to true (no user namespace), and the unmasked case with a privileged pod sets it to false (use a user namespace), to verify the /proc mount is unmasked in this case. Signed-off-by: Rodrigo Campos --- test/e2e_node/proc_mount_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/e2e_node/proc_mount_test.go b/test/e2e_node/proc_mount_test.go index 109fdb849f2..e0023ba8d73 100644 --- a/test/e2e_node/proc_mount_test.go +++ b/test/e2e_node/proc_mount_test.go @@ -41,7 +41,7 @@ var _ = SIGDescribe("DefaultProcMount [LinuxOnly]", framework.WithNodeConformanc f.NamespacePodSecurityLevel = admissionapi.LevelBaseline ginkgo.It("will mask proc mounts by default", func(ctx context.Context) { - testProcMount(ctx, f, v1.DefaultProcMount, gomega.BeNumerically(">", 1), gomega.BeNumerically(">", 0)) + testProcMount(ctx, f, v1.DefaultProcMount, true, gomega.BeNumerically(">", 1), gomega.BeNumerically(">", 0)) }) }) @@ -85,11 +85,11 @@ var _ = SIGDescribe("ProcMount [LinuxOnly]", feature.ProcMountType, feature.User if !supportsUserNS(ctx, f) { e2eskipper.Skipf("runtime does not support user namespaces") } - testProcMount(ctx, f, v1.UnmaskedProcMount, gomega.Equal(1), gomega.BeZero()) + testProcMount(ctx, f, v1.UnmaskedProcMount, false, gomega.Equal(1), gomega.BeZero()) }) }) -func testProcMount(ctx context.Context, f *framework.Framework, pmt v1.ProcMountType, expectedLines gomegatypes.GomegaMatcher, expectedReadOnly gomegatypes.GomegaMatcher) { +func testProcMount(ctx context.Context, f *framework.Framework, pmt v1.ProcMountType, hostUsers bool, expectedLines gomegatypes.GomegaMatcher, expectedReadOnly gomegatypes.GomegaMatcher) { ginkgo.By("creating a target pod") podClient := e2epod.NewPodClient(f) pod := podClient.CreateSync(ctx, &v1.Pod{ @@ -106,7 +106,7 @@ func testProcMount(ctx context.Context, f *framework.Framework, pmt v1.ProcMount }, }, }, - HostUsers: &falseVar, + HostUsers: &hostUsers, }, })