diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 31c213ca322..b010c726a36 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -6322,7 +6322,7 @@ "properties": { "configSource": { "$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigSource", - "description": "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26." + "description": "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed." }, "externalID": { "description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966", diff --git a/api/openapi-spec/v3/api__v1_openapi.json b/api/openapi-spec/v3/api__v1_openapi.json index 2d9d2e66511..854e3d77d95 100644 --- a/api/openapi-spec/v3/api__v1_openapi.json +++ b/api/openapi-spec/v3/api__v1_openapi.json @@ -3594,7 +3594,7 @@ "$ref": "#/components/schemas/io.k8s.api.core.v1.NodeConfigSource" } ], - "description": "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26." + "description": "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed." }, "externalID": { "description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966", diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index 9e121f0b9fa..dfdddb6b5fa 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -235,13 +235,6 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API klog.InfoS("unsupported configuration:KubeletCgroups is not within KubeReservedCgroup") } - // The features.DynamicKubeletConfig is locked to false, - // feature gate is not locked using the LockedToDefault flag - // to make sure node authorizer can keep working with the older nodes - if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { - return fmt.Errorf("cannot set feature gate %v to %v, feature is locked to %v", features.DynamicKubeletConfig, true, false) - } - // construct a KubeletServer from kubeletFlags and kubeletConfig kubeletServer := &options.KubeletServer{ KubeletFlags: *kubeletFlags, diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index 8d6e7cc1ef6..ec105a41f44 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -4160,7 +4160,7 @@ type NodeSpec struct { // +optional Taints []Taint - // Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26. + // Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed. // +optional ConfigSource *NodeConfigSource diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index 94dc66d80c9..325e7d94905 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -5259,6 +5259,8 @@ func ValidateNodeUpdate(node, oldNode *core.Node) field.ErrorList { } // validation specific to Node.Spec.ConfigSource +// The field ConfigSource is deprecated and will not be used. The validation is kept in place +// for the backward compatibility func validateNodeConfigSourceSpec(source *core.NodeConfigSource, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} count := int(0) @@ -5276,6 +5278,8 @@ func validateNodeConfigSourceSpec(source *core.NodeConfigSource, fldPath *field. } // validation specific to Node.Spec.ConfigSource.ConfigMap +// The field ConfigSource is deprecated and will not be used. The validation is kept in place +// for the backward compatibility func validateConfigMapNodeConfigSourceSpec(source *core.ConfigMapNodeConfigSource, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} // uid and resourceVersion must not be set in spec diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 4b20719c12a..457f8c030a6 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -256,12 +256,6 @@ const ( // Enables usage of hugepages- in downward API. DownwardAPIHugePages featuregate.Feature = "DownwardAPIHugePages" - // owner: @mtaufen - // alpha: v1.4 - // beta: v1.11 - // deprecated: 1.22 - DynamicKubeletConfig featuregate.Feature = "DynamicKubeletConfig" - // owner: @andrewsykim // kep: https://kep.k8s.io/1672 // alpha: v1.20 @@ -863,8 +857,6 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS DownwardAPIHugePages: {Default: true, PreRelease: featuregate.Beta}, // on by default in 1.22 - DynamicKubeletConfig: {Default: false, PreRelease: featuregate.Deprecated}, // feature gate is deprecated in 1.22, kubelet logic is removed in 1.24, api server logic can be removed in 1.26 - EndpointSliceTerminatingCondition: {Default: true, PreRelease: featuregate.Beta}, EphemeralContainers: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27 diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 03e44137a17..3de8cacef21 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -19913,7 +19913,7 @@ func schema_k8sio_api_core_v1_NodeSpec(ref common.ReferenceCallback) common.Open }, "configSource": { SchemaProps: spec.SchemaProps{ - Description: "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26.", + Description: "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed.", Ref: ref("k8s.io/api/core/v1.NodeConfigSource"), }, }, diff --git a/pkg/registry/core/node/strategy.go b/pkg/registry/core/node/strategy.go index bf6b6a57708..79298df78ed 100644 --- a/pkg/registry/core/node/strategy.go +++ b/pkg/registry/core/node/strategy.go @@ -34,11 +34,9 @@ import ( "k8s.io/apiserver/pkg/registry/generic" pkgstorage "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/validation" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/client" proxyutil "k8s.io/kubernetes/pkg/proxy/util" "sigs.k8s.io/structured-merge-diff/v4/fieldpath" @@ -94,13 +92,13 @@ func (nodeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Objec func dropDisabledFields(node *api.Node, oldNode *api.Node) { // Nodes allow *all* fields, including status, to be set on create. // for create - if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && oldNode == nil { + if oldNode == nil { node.Spec.ConfigSource = nil node.Status.Config = nil } // for update - if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && !nodeConfigSourceInUse(oldNode) && oldNode != nil { + if !nodeConfigSourceInUse(oldNode) && oldNode != nil { node.Spec.ConfigSource = nil } @@ -170,7 +168,7 @@ func (nodeStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime oldNode := old.(*api.Node) newNode.Spec = oldNode.Spec - if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && !nodeStatusConfigInUse(oldNode) { + if !nodeStatusConfigInUse(oldNode) { newNode.Status.Config = nil } } @@ -274,7 +272,7 @@ func dynamicKubeletConfigIsDeprecatedWarning(obj runtime.Object) []string { if newNode.Spec.ConfigSource != nil { var warnings []string // KEP https://github.com/kubernetes/enhancements/issues/281 - warnings = append(warnings, "spec.configSource: deprecated in v1.22, support removal is planned in v1.23") + warnings = append(warnings, "spec.configSource: the feature is removed") return warnings } return nil diff --git a/pkg/registry/core/node/strategy_test.go b/pkg/registry/core/node/strategy_test.go index 80c2a39cdac..f17cc14b41d 100644 --- a/pkg/registry/core/node/strategy_test.go +++ b/pkg/registry/core/node/strategy_test.go @@ -27,11 +27,8 @@ import ( "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/diff" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/features" // ensure types are installed _ "k8s.io/kubernetes/pkg/apis/core/install" @@ -88,11 +85,10 @@ func makeNode(podCIDRs []string, addSpecDynamicConfig bool, addStatusDynamicConf func TestDropFields(t *testing.T) { testCases := []struct { - name string - node *api.Node - oldNode *api.Node - compareNode *api.Node - enableNodeDynamicConfig bool + name string + node *api.Node + oldNode *api.Node + compareNode *api.Node }{ { name: "nil pod cidrs", @@ -127,60 +123,45 @@ func TestDropFields(t *testing.T) { compareNode: makeNode([]string{"2000::/10", "10.0.0.0/8"}, false, false), }, { - name: "new with no Spec.ConfigSource and no Status.Config , enableNodeDynamicConfig disabled", - enableNodeDynamicConfig: false, - node: makeNode(nil, false, false), - oldNode: nil, - compareNode: makeNode(nil, false, false), + name: "new with no Spec.ConfigSource and no Status.Config", + node: makeNode(nil, false, false), + oldNode: nil, + compareNode: makeNode(nil, false, false), }, { - name: "new with Spec.ConfigSource and no Status.Config, enableNodeDynamicConfig disabled", - enableNodeDynamicConfig: false, - node: makeNode(nil, true, false), - oldNode: nil, - compareNode: makeNode(nil, false, false), + name: "new with Spec.ConfigSource and no Status.Config", + node: makeNode(nil, true, false), + oldNode: nil, + compareNode: makeNode(nil, false, false), }, { - name: "new with Spec.ConfigSource and Status.Config, enableNodeDynamicConfig disabled", - enableNodeDynamicConfig: false, - node: makeNode(nil, true, true), - oldNode: nil, - compareNode: makeNode(nil, false, false), + name: "new with Spec.ConfigSource and Status.Config", + node: makeNode(nil, true, true), + oldNode: nil, + compareNode: makeNode(nil, false, false), }, { - name: "update with Spec.ConfigSource and Status.Config (old has none), enableNodeDynamicConfig disabled", - enableNodeDynamicConfig: false, - node: makeNode(nil, true, true), - oldNode: makeNode(nil, false, false), - compareNode: makeNode(nil, false, true), + name: "update with Spec.ConfigSource and Status.Config (old has none)", + node: makeNode(nil, true, true), + oldNode: makeNode(nil, false, false), + compareNode: makeNode(nil, false, true), }, { - name: "update with Spec.ConfigSource and Status.Config (old has them), enableNodeDynamicConfig disabled", - enableNodeDynamicConfig: false, - node: makeNode(nil, true, true), - oldNode: makeNode(nil, true, true), - compareNode: makeNode(nil, true, true), + name: "update with Spec.ConfigSource and Status.Config (old has them)", + node: makeNode(nil, true, true), + oldNode: makeNode(nil, true, true), + compareNode: makeNode(nil, true, true), }, { - name: "update with Spec.ConfigSource and Status.Config (old has Status.Config), enableNodeDynamicConfig disabled", - enableNodeDynamicConfig: false, - node: makeNode(nil, true, true), - oldNode: makeNode(nil, false, true), - compareNode: makeNode(nil, false, true), - }, - { - name: "new with Spec.ConfigSource and Status.Config, enableNodeDynamicConfig enabled", - enableNodeDynamicConfig: true, - node: makeNode(nil, true, true), - oldNode: nil, - compareNode: makeNode(nil, true, true), + name: "update with Spec.ConfigSource and Status.Config (old has Status.Config)", + node: makeNode(nil, true, true), + oldNode: makeNode(nil, false, true), + compareNode: makeNode(nil, false, true), }, } for _, tc := range testCases { func() { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DynamicKubeletConfig, tc.enableNodeDynamicConfig)() - dropDisabledFields(tc.node, tc.oldNode) old := tc.oldNode.DeepCopy() diff --git a/plugin/pkg/auth/authorizer/node/graph.go b/plugin/pkg/auth/authorizer/node/graph.go index ef275df85cd..bd5feea89f2 100644 --- a/plugin/pkg/auth/authorizer/node/graph.go +++ b/plugin/pkg/auth/authorizer/node/graph.go @@ -476,31 +476,3 @@ func (g *Graph) DeleteVolumeAttachment(name string) { defer g.lock.Unlock() g.deleteVertex_locked(vaVertexType, "", name) } - -// SetNodeConfigMap sets up edges for the Node.Spec.ConfigSource.ConfigMap relationship: -// -// configmap -> node -func (g *Graph) SetNodeConfigMap(nodeName, configMapName, configMapNamespace string) { - start := time.Now() - defer func() { - graphActionsDuration.WithLabelValues("SetNodeConfigMap").Observe(time.Since(start).Seconds()) - }() - g.lock.Lock() - defer g.lock.Unlock() - - // TODO(mtaufen): ensure len(nodeName) > 0 in all cases (would sure be nice to have a dependently-typed language here...) - - // clear edges configmaps -> node where the destination is the current node *only* - // at present, a node can only have one *direct* configmap reference at a time - g.deleteEdges_locked(configMapVertexType, nodeVertexType, "", nodeName) - - // establish new edges if we have a real ConfigMap to reference - if len(configMapName) > 0 && len(configMapNamespace) > 0 { - configmapVertex := g.getOrCreateVertex_locked(configMapVertexType, configMapNamespace, configMapName) - nodeVertex := g.getOrCreateVertex_locked(nodeVertexType, "", nodeName) - e := newDestinationEdge(configmapVertex, nodeVertex, nodeVertex) - g.graph.SetEdge(e) - g.addEdgeToDestinationIndex_locked(e) - } - -} diff --git a/plugin/pkg/auth/authorizer/node/graph_populator.go b/plugin/pkg/auth/authorizer/node/graph_populator.go index 5a21691f9a1..1eec6afb42e 100644 --- a/plugin/pkg/auth/authorizer/node/graph_populator.go +++ b/plugin/pkg/auth/authorizer/node/graph_populator.go @@ -17,7 +17,6 @@ limitations under the License. package node import ( - "fmt" "time" "k8s.io/klog/v2" @@ -25,11 +24,9 @@ import ( corev1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/util/wait" - utilfeature "k8s.io/apiserver/pkg/util/feature" corev1informers "k8s.io/client-go/informers/core/v1" storageinformers "k8s.io/client-go/informers/storage/v1" "k8s.io/client-go/tools/cache" - "k8s.io/kubernetes/pkg/features" ) type graphPopulator struct { @@ -49,15 +46,6 @@ func AddGraphEventHandlers( var hasSynced []cache.InformerSynced - if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) { - nodes.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - AddFunc: g.addNode, - UpdateFunc: g.updateNode, - DeleteFunc: g.deleteNode, - }) - hasSynced = append(hasSynced, nodes.Informer().HasSynced) - } - pods.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: g.addPod, UpdateFunc: g.updatePod, @@ -82,62 +70,6 @@ func AddGraphEventHandlers( go cache.WaitForNamedCacheSync("node_authorizer", wait.NeverStop, hasSynced...) } -func (g *graphPopulator) addNode(obj interface{}) { - g.updateNode(nil, obj) -} - -func (g *graphPopulator) updateNode(oldObj, obj interface{}) { - node := obj.(*corev1.Node) - var oldNode *corev1.Node - if oldObj != nil { - oldNode = oldObj.(*corev1.Node) - } - - // we only set up rules for ConfigMap today, because that is the only reference type - - var name, namespace string - if source := node.Spec.ConfigSource; source != nil && source.ConfigMap != nil { - name = source.ConfigMap.Name - namespace = source.ConfigMap.Namespace - } - - var oldName, oldNamespace string - if oldNode != nil { - if oldSource := oldNode.Spec.ConfigSource; oldSource != nil && oldSource.ConfigMap != nil { - oldName = oldSource.ConfigMap.Name - oldNamespace = oldSource.ConfigMap.Namespace - } - } - - // if Node.Spec.ConfigSource wasn't updated, nothing for us to do - if name == oldName && namespace == oldNamespace { - return - } - - path := "nil" - if node.Spec.ConfigSource != nil { - path = fmt.Sprintf("%s/%s", namespace, name) - } - klog.V(4).Infof("updateNode configSource reference to %s for node %s", path, node.Name) - g.graph.SetNodeConfigMap(node.Name, name, namespace) -} - -func (g *graphPopulator) deleteNode(obj interface{}) { - if tombstone, ok := obj.(cache.DeletedFinalStateUnknown); ok { - obj = tombstone.Obj - } - node, ok := obj.(*corev1.Node) - if !ok { - klog.Infof("unexpected type %T", obj) - return - } - - // NOTE: We don't remove the node, because if the node is re-created not all pod -> node - // links are re-established (we don't get relevant events because the no mutations need - // to happen in the API; the state is already there). - g.graph.SetNodeConfigMap(node.Name, "", "") -} - func (g *graphPopulator) addPod(obj interface{}) { g.updatePod(nil, obj) } diff --git a/plugin/pkg/auth/authorizer/node/graph_test.go b/plugin/pkg/auth/authorizer/node/graph_test.go index cb1dc31d792..939bb6399ac 100644 --- a/plugin/pkg/auth/authorizer/node/graph_test.go +++ b/plugin/pkg/auth/authorizer/node/graph_test.go @@ -343,74 +343,4 @@ func TestIndex(t *testing.T) { "configmap:ns/cm3": {"node:node1=1", "node:node2=1", "node:node3=1"}, "serviceAccount:ns/sa1": {"node:node1=1", "node:node2=1", "node:node3=1"}, }) - - // Set node->configmap references - g.SetNodeConfigMap("node1", "cm1", "ns") - g.SetNodeConfigMap("node2", "cm1", "ns") - g.SetNodeConfigMap("node3", "cm1", "ns") - g.SetNodeConfigMap("node4", "cm1", "ns") - expectGraph(map[string][]string{ - "node:node1": {}, - "node:node2": {}, - "node:node3": {}, - "node:node4": {}, - "pod:ns/pod2": {"node:node2"}, - "pod:ns/pod3": {"node:node3"}, - "pod:ns/pod4": {"node:node1"}, - "configmap:ns/cm1": {"node:node1", "node:node2", "node:node3", "node:node4", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - "configmap:ns/cm2": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - "configmap:ns/cm3": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - "serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - }) - expectIndex(map[string][]string{ - "configmap:ns/cm1": {"node:node1=2", "node:node2=2", "node:node3=2", "node:node4=1"}, - "configmap:ns/cm2": {"node:node1=1", "node:node2=1", "node:node3=1"}, - "configmap:ns/cm3": {"node:node1=1", "node:node2=1", "node:node3=1"}, - "serviceAccount:ns/sa1": {"node:node1=1", "node:node2=1", "node:node3=1"}, - }) - - // Update node->configmap reference - g.SetNodeConfigMap("node1", "cm2", "ns") - expectGraph(map[string][]string{ - "node:node1": {}, - "node:node2": {}, - "node:node3": {}, - "node:node4": {}, - "pod:ns/pod2": {"node:node2"}, - "pod:ns/pod3": {"node:node3"}, - "pod:ns/pod4": {"node:node1"}, - "configmap:ns/cm1": {"node:node2", "node:node3", "node:node4", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - "configmap:ns/cm2": {"node:node1", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - "configmap:ns/cm3": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - "serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - }) - expectIndex(map[string][]string{ - "configmap:ns/cm1": {"node:node1=1", "node:node2=2", "node:node3=2", "node:node4=1"}, - "configmap:ns/cm2": {"node:node1=2", "node:node2=1", "node:node3=1"}, - "configmap:ns/cm3": {"node:node1=1", "node:node2=1", "node:node3=1"}, - "serviceAccount:ns/sa1": {"node:node1=1", "node:node2=1", "node:node3=1"}, - }) - - // Remove node->configmap reference - g.SetNodeConfigMap("node1", "", "") - g.SetNodeConfigMap("node4", "", "") - expectGraph(map[string][]string{ - "node:node1": {}, - "node:node2": {}, - "node:node3": {}, - "node:node4": {}, - "pod:ns/pod2": {"node:node2"}, - "pod:ns/pod3": {"node:node3"}, - "pod:ns/pod4": {"node:node1"}, - "configmap:ns/cm1": {"node:node2", "node:node3", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - "configmap:ns/cm2": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - "configmap:ns/cm3": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - "serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"}, - }) - expectIndex(map[string][]string{ - "configmap:ns/cm1": {"node:node1=1", "node:node2=2", "node:node3=2"}, - "configmap:ns/cm2": {"node:node1=1", "node:node2=1", "node:node3=1"}, - "configmap:ns/cm3": {"node:node1=1", "node:node2=1", "node:node3=1"}, - "serviceAccount:ns/sa1": {"node:node1=1", "node:node2=1", "node:node3=1"}, - }) } diff --git a/plugin/pkg/auth/authorizer/node/node_authorizer_test.go b/plugin/pkg/auth/authorizer/node/node_authorizer_test.go index 5e4339db60d..921a22ca126 100644 --- a/plugin/pkg/auth/authorizer/node/node_authorizer_test.go +++ b/plugin/pkg/auth/authorizer/node/node_authorizer_test.go @@ -30,7 +30,6 @@ import ( corev1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -68,11 +67,6 @@ func TestAuthorizer(t *testing.T) { expect authorizer.Decision features featuregate.FeatureGate }{ - { - name: "allowed node configmap", - attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node0-configmap", Namespace: "ns0"}, - expect: authorizer.DecisionAllow, - }, { name: "allowed configmap", attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"}, @@ -128,12 +122,6 @@ func TestAuthorizer(t *testing.T) { attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumes", Name: "pv0-pod0-node0-ns0", Namespace: ""}, expect: authorizer.DecisionAllow, }, - - { - name: "disallowed node configmap", - attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node1-configmap", Namespace: "ns0"}, - expect: authorizer.DecisionNoOpinion, - }, { name: "disallowed configmap", attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"}, @@ -385,36 +373,23 @@ func TestAuthorizerSharedResources(t *testing.T) { } g.AddPod(pod3) - g.SetNodeConfigMap("node1", "shared-configmap", "ns1") - g.SetNodeConfigMap("node2", "shared-configmap", "ns1") - g.SetNodeConfigMap("node3", "configmap", "ns1") - testcases := []struct { - User user.Info - Secret string - ConfigMap string - ExpectAllowed bool + User user.Info + Secret string + ConfigMap string + Decision authorizer.Decision }{ - {User: node1, ExpectAllowed: true, Secret: "node1-only"}, - {User: node1, ExpectAllowed: true, Secret: "node1-node2-only"}, - {User: node1, ExpectAllowed: true, Secret: "shared-all"}, + {User: node1, Decision: authorizer.DecisionAllow, Secret: "node1-only"}, + {User: node1, Decision: authorizer.DecisionAllow, Secret: "node1-node2-only"}, + {User: node1, Decision: authorizer.DecisionAllow, Secret: "shared-all"}, - {User: node2, ExpectAllowed: false, Secret: "node1-only"}, - {User: node2, ExpectAllowed: true, Secret: "node1-node2-only"}, - {User: node2, ExpectAllowed: true, Secret: "shared-all"}, + {User: node2, Decision: authorizer.DecisionNoOpinion, Secret: "node1-only"}, + {User: node2, Decision: authorizer.DecisionAllow, Secret: "node1-node2-only"}, + {User: node2, Decision: authorizer.DecisionAllow, Secret: "shared-all"}, - {User: node3, ExpectAllowed: false, Secret: "node1-only"}, - {User: node3, ExpectAllowed: false, Secret: "node1-node2-only"}, - {User: node3, ExpectAllowed: true, Secret: "shared-all"}, - - {User: node1, ExpectAllowed: true, ConfigMap: "shared-configmap"}, - {User: node1, ExpectAllowed: false, ConfigMap: "configmap"}, - - {User: node2, ExpectAllowed: true, ConfigMap: "shared-configmap"}, - {User: node2, ExpectAllowed: false, ConfigMap: "configmap"}, - - {User: node3, ExpectAllowed: false, ConfigMap: "shared-configmap"}, - {User: node3, ExpectAllowed: true, ConfigMap: "configmap"}, + {User: node3, Decision: authorizer.DecisionNoOpinion, Secret: "node1-only"}, + {User: node3, Decision: authorizer.DecisionNoOpinion, Secret: "node1-node2-only"}, + {User: node3, Decision: authorizer.DecisionAllow, Secret: "shared-all"}, } for i, tc := range testcases { @@ -439,8 +414,8 @@ func TestAuthorizerSharedResources(t *testing.T) { t.Fatalf("test case must include a request for a Secret or ConfigMap") } - if (decision == authorizer.DecisionAllow) != tc.ExpectAllowed { - t.Errorf("%d: expected %v, got %v", i, tc.ExpectAllowed, decision) + if decision != tc.Decision { + t.Errorf("%d: expected %v, got %v", i, tc.Decision, decision) } } @@ -629,11 +604,6 @@ func BenchmarkAuthorization(b *testing.B) { expect authorizer.Decision features featuregate.FeatureGate }{ - { - name: "allowed node configmap", - attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node0-configmap", Namespace: "ns0"}, - expect: authorizer.DecisionAllow, - }, { name: "allowed configmap", attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"}, @@ -649,12 +619,6 @@ func BenchmarkAuthorization(b *testing.B) { attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-shared", Namespace: "ns0"}, expect: authorizer.DecisionAllow, }, - - { - name: "disallowed node configmap", - attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node1-configmap", Namespace: "ns0"}, - expect: authorizer.DecisionNoOpinion, - }, { name: "disallowed configmap", attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"}, @@ -779,9 +743,6 @@ func BenchmarkAuthorization(b *testing.B) { func populate(graph *Graph, nodes []*corev1.Node, pods []*corev1.Pod, pvs []*corev1.PersistentVolume, attachments []*storagev1.VolumeAttachment) { p := &graphPopulator{} p.graph = graph - for _, node := range nodes { - p.addNode(node) - } for _, pod := range pods { p.addPod(pod) } @@ -830,19 +791,9 @@ func generate(opts *sampleDataOpts) ([]*corev1.Node, []*corev1.Pod, []*corev1.Pe attachments = append(attachments, attachment) } - name := fmt.Sprintf("%s-configmap", nodeName) nodes = append(nodes, &corev1.Node{ ObjectMeta: metav1.ObjectMeta{Name: nodeName}, - Spec: corev1.NodeSpec{ - ConfigSource: &corev1.NodeConfigSource{ - ConfigMap: &corev1.ConfigMapNodeConfigSource{ - Name: name, - Namespace: "ns0", - UID: types.UID(fmt.Sprintf("ns0-%s", name)), - KubeletConfigKey: "kubelet", - }, - }, - }, + Spec: corev1.NodeSpec{}, }) } return nodes, pods, pvs, attachments diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 2ab80f07a99..c43dbc3bace 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -2413,7 +2413,7 @@ message NodeSpec { // +optional repeated Taint taints = 5; - // Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26. + // Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed. // +optional optional NodeConfigSource configSource = 6; diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index fea7acfb42c..adfad114e4a 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -4898,7 +4898,7 @@ type NodeSpec struct { // +optional Taints []Taint `json:"taints,omitempty" protobuf:"bytes,5,opt,name=taints"` - // Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26. + // Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed. // +optional ConfigSource *NodeConfigSource `json:"configSource,omitempty" protobuf:"bytes,6,opt,name=configSource"` diff --git a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index f00a81e4e6f..4a2394a5246 100644 --- a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -1189,7 +1189,7 @@ var map_NodeSpec = map[string]string{ "providerID": "ID of the node assigned by the cloud provider in the format: ://", "unschedulable": "Unschedulable controls node schedulability of new pods. By default, node is schedulable. More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration", "taints": "If specified, the node's taints.", - "configSource": "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26.", + "configSource": "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed.", "externalID": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966", } diff --git a/test/integration/auth/node_test.go b/test/integration/auth/node_test.go index 60e4b029483..51b599175f1 100644 --- a/test/integration/auth/node_test.go +++ b/test/integration/auth/node_test.go @@ -33,11 +33,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" - utilfeature "k8s.io/apiserver/pkg/util/feature" clientset "k8s.io/client-go/kubernetes" - featuregatetesting "k8s.io/component-base/featuregate/testing" kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/test/integration/framework" "k8s.io/utils/pointer" ) @@ -52,9 +49,6 @@ func TestNodeAuthorizer(t *testing.T) { tokenNode2 = "node2-token" ) - // Enable DynamicKubeletConfig feature so that Node.Spec.ConfigSource can be set - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DynamicKubeletConfig, true)() - tokenFile, err := os.CreateTemp("", "kubeconfig") if err != nil { t.Fatal(err) @@ -106,9 +100,6 @@ func TestNodeAuthorizer(t *testing.T) { if _, err := superuserClient.CoreV1().ConfigMaps("ns").Create(context.TODO(), &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "myconfigmap"}}, metav1.CreateOptions{}); err != nil { t.Fatal(err) } - if _, err := superuserClient.CoreV1().ConfigMaps("ns").Create(context.TODO(), &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "myconfigmapconfigsource"}}, metav1.CreateOptions{}); err != nil { - t.Fatal(err) - } pvName := "mypv" if _, err := superuserClientExternal.StorageV1().VolumeAttachments().Create(context.TODO(), &storagev1.VolumeAttachment{ ObjectMeta: metav1.ObjectMeta{Name: "myattachment"}, @@ -160,12 +151,6 @@ func TestNodeAuthorizer(t *testing.T) { return err } } - getConfigMapConfigSource := func(client clientset.Interface) func() error { - return func() error { - _, err := client.CoreV1().ConfigMaps("ns").Get(context.TODO(), "myconfigmapconfigsource", metav1.GetOptions{}) - return err - } - } getPVC := func(client clientset.Interface) func() error { return func() error { _, err := client.CoreV1().PersistentVolumeClaims("ns").Get(context.TODO(), "mypvc", metav1.GetOptions{}) @@ -260,34 +245,6 @@ func TestNodeAuthorizer(t *testing.T) { return err } } - setNode2ConfigSource := func(client clientset.Interface) func() error { - return func() error { - node2, err := client.CoreV1().Nodes().Get(context.TODO(), "node2", metav1.GetOptions{}) - if err != nil { - return err - } - node2.Spec.ConfigSource = &corev1.NodeConfigSource{ - ConfigMap: &corev1.ConfigMapNodeConfigSource{ - Namespace: "ns", - Name: "myconfigmapconfigsource", - KubeletConfigKey: "kubelet", - }, - } - _, err = client.CoreV1().Nodes().Update(context.TODO(), node2, metav1.UpdateOptions{}) - return err - } - } - unsetNode2ConfigSource := func(client clientset.Interface) func() error { - return func() error { - node2, err := client.CoreV1().Nodes().Get(context.TODO(), "node2", metav1.GetOptions{}) - if err != nil { - return err - } - node2.Spec.ConfigSource = nil - _, err = client.CoreV1().Nodes().Update(context.TODO(), node2, metav1.UpdateOptions{}) - return err - } - } updateNode2Status := func(client clientset.Interface) func() error { return func() error { _, err := client.CoreV1().Nodes().UpdateStatus(context.TODO(), &corev1.Node{ @@ -578,20 +535,6 @@ func TestNodeAuthorizer(t *testing.T) { // create node2 again expectAllowed(t, createNode2(node2Client)) - // node2 can not set its own config source - expectForbidden(t, setNode2ConfigSource(node2Client)) - // node2 can not access the configmap config source yet - expectForbidden(t, getConfigMapConfigSource(node2Client)) - // superuser can access the configmap config source - expectAllowed(t, getConfigMapConfigSource(superuserClient)) - // superuser can set node2's config source - expectAllowed(t, setNode2ConfigSource(superuserClient)) - // node2 can now get the configmap assigned as its config source - expectAllowed(t, getConfigMapConfigSource(node2Client)) - // superuser can unset node2's config source - expectAllowed(t, unsetNode2ConfigSource(superuserClient)) - // node2 can no longer get the configmap after it is unassigned as its config source - expectForbidden(t, getConfigMapConfigSource(node2Client)) // clean up node2 expectAllowed(t, deleteNode2(superuserClient))