mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 10:20:51 +00:00
Merge pull request #112643 from SergeyKanzhelev/removeDynamicKubeletConfig
remove DynamicKubeletConfig feature gate from the code
This commit is contained in:
commit
525280d285
2
api/openapi-spec/swagger.json
generated
2
api/openapi-spec/swagger.json
generated
@ -6322,7 +6322,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"configSource": {
|
"configSource": {
|
||||||
"$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigSource",
|
"$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": {
|
"externalID": {
|
||||||
"description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
|
"description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
|
||||||
|
@ -3594,7 +3594,7 @@
|
|||||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.NodeConfigSource"
|
"$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": {
|
"externalID": {
|
||||||
"description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
|
"description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
|
||||||
|
@ -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")
|
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
|
// construct a KubeletServer from kubeletFlags and kubeletConfig
|
||||||
kubeletServer := &options.KubeletServer{
|
kubeletServer := &options.KubeletServer{
|
||||||
KubeletFlags: *kubeletFlags,
|
KubeletFlags: *kubeletFlags,
|
||||||
|
@ -4160,7 +4160,7 @@ type NodeSpec struct {
|
|||||||
// +optional
|
// +optional
|
||||||
Taints []Taint
|
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
|
// +optional
|
||||||
ConfigSource *NodeConfigSource
|
ConfigSource *NodeConfigSource
|
||||||
|
|
||||||
|
@ -5259,6 +5259,8 @@ func ValidateNodeUpdate(node, oldNode *core.Node) field.ErrorList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validation specific to Node.Spec.ConfigSource
|
// 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 {
|
func validateNodeConfigSourceSpec(source *core.NodeConfigSource, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
count := int(0)
|
count := int(0)
|
||||||
@ -5276,6 +5278,8 @@ func validateNodeConfigSourceSpec(source *core.NodeConfigSource, fldPath *field.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validation specific to Node.Spec.ConfigSource.ConfigMap
|
// 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 {
|
func validateConfigMapNodeConfigSourceSpec(source *core.ConfigMapNodeConfigSource, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
// uid and resourceVersion must not be set in spec
|
// uid and resourceVersion must not be set in spec
|
||||||
|
@ -256,12 +256,6 @@ const (
|
|||||||
// Enables usage of hugepages-<size> in downward API.
|
// Enables usage of hugepages-<size> in downward API.
|
||||||
DownwardAPIHugePages featuregate.Feature = "DownwardAPIHugePages"
|
DownwardAPIHugePages featuregate.Feature = "DownwardAPIHugePages"
|
||||||
|
|
||||||
// owner: @mtaufen
|
|
||||||
// alpha: v1.4
|
|
||||||
// beta: v1.11
|
|
||||||
// deprecated: 1.22
|
|
||||||
DynamicKubeletConfig featuregate.Feature = "DynamicKubeletConfig"
|
|
||||||
|
|
||||||
// owner: @andrewsykim
|
// owner: @andrewsykim
|
||||||
// kep: https://kep.k8s.io/1672
|
// kep: https://kep.k8s.io/1672
|
||||||
// alpha: v1.20
|
// 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
|
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},
|
EndpointSliceTerminatingCondition: {Default: true, PreRelease: featuregate.Beta},
|
||||||
|
|
||||||
EphemeralContainers: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27
|
EphemeralContainers: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27
|
||||||
|
2
pkg/generated/openapi/zz_generated.openapi.go
generated
2
pkg/generated/openapi/zz_generated.openapi.go
generated
@ -19913,7 +19913,7 @@ func schema_k8sio_api_core_v1_NodeSpec(ref common.ReferenceCallback) common.Open
|
|||||||
},
|
},
|
||||||
"configSource": {
|
"configSource": {
|
||||||
SchemaProps: spec.SchemaProps{
|
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"),
|
Ref: ref("k8s.io/api/core/v1.NodeConfigSource"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -34,11 +34,9 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/registry/generic"
|
"k8s.io/apiserver/pkg/registry/generic"
|
||||||
pkgstorage "k8s.io/apiserver/pkg/storage"
|
pkgstorage "k8s.io/apiserver/pkg/storage"
|
||||||
"k8s.io/apiserver/pkg/storage/names"
|
"k8s.io/apiserver/pkg/storage/names"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
"k8s.io/kubernetes/pkg/apis/core/validation"
|
"k8s.io/kubernetes/pkg/apis/core/validation"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/kubelet/client"
|
"k8s.io/kubernetes/pkg/kubelet/client"
|
||||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
"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) {
|
func dropDisabledFields(node *api.Node, oldNode *api.Node) {
|
||||||
// Nodes allow *all* fields, including status, to be set on create.
|
// Nodes allow *all* fields, including status, to be set on create.
|
||||||
// for create
|
// for create
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && oldNode == nil {
|
if oldNode == nil {
|
||||||
node.Spec.ConfigSource = nil
|
node.Spec.ConfigSource = nil
|
||||||
node.Status.Config = nil
|
node.Status.Config = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// for update
|
// for update
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && !nodeConfigSourceInUse(oldNode) && oldNode != nil {
|
if !nodeConfigSourceInUse(oldNode) && oldNode != nil {
|
||||||
node.Spec.ConfigSource = nil
|
node.Spec.ConfigSource = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +168,7 @@ func (nodeStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime
|
|||||||
oldNode := old.(*api.Node)
|
oldNode := old.(*api.Node)
|
||||||
newNode.Spec = oldNode.Spec
|
newNode.Spec = oldNode.Spec
|
||||||
|
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && !nodeStatusConfigInUse(oldNode) {
|
if !nodeStatusConfigInUse(oldNode) {
|
||||||
newNode.Status.Config = nil
|
newNode.Status.Config = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,7 +272,7 @@ func dynamicKubeletConfigIsDeprecatedWarning(obj runtime.Object) []string {
|
|||||||
if newNode.Spec.ConfigSource != nil {
|
if newNode.Spec.ConfigSource != nil {
|
||||||
var warnings []string
|
var warnings []string
|
||||||
// KEP https://github.com/kubernetes/enhancements/issues/281
|
// 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 warnings
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -27,11 +27,8 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"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"
|
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
|
|
||||||
// ensure types are installed
|
// ensure types are installed
|
||||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||||
@ -92,7 +89,6 @@ func TestDropFields(t *testing.T) {
|
|||||||
node *api.Node
|
node *api.Node
|
||||||
oldNode *api.Node
|
oldNode *api.Node
|
||||||
compareNode *api.Node
|
compareNode *api.Node
|
||||||
enableNodeDynamicConfig bool
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "nil pod cidrs",
|
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),
|
compareNode: makeNode([]string{"2000::/10", "10.0.0.0/8"}, false, false),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "new with no Spec.ConfigSource and no Status.Config , enableNodeDynamicConfig disabled",
|
name: "new with no Spec.ConfigSource and no Status.Config",
|
||||||
enableNodeDynamicConfig: false,
|
|
||||||
node: makeNode(nil, false, false),
|
node: makeNode(nil, false, false),
|
||||||
oldNode: nil,
|
oldNode: nil,
|
||||||
compareNode: makeNode(nil, false, false),
|
compareNode: makeNode(nil, false, false),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "new with Spec.ConfigSource and no Status.Config, enableNodeDynamicConfig disabled",
|
name: "new with Spec.ConfigSource and no Status.Config",
|
||||||
enableNodeDynamicConfig: false,
|
|
||||||
node: makeNode(nil, true, false),
|
node: makeNode(nil, true, false),
|
||||||
oldNode: nil,
|
oldNode: nil,
|
||||||
compareNode: makeNode(nil, false, false),
|
compareNode: makeNode(nil, false, false),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "new with Spec.ConfigSource and Status.Config, enableNodeDynamicConfig disabled",
|
name: "new with Spec.ConfigSource and Status.Config",
|
||||||
enableNodeDynamicConfig: false,
|
|
||||||
node: makeNode(nil, true, true),
|
node: makeNode(nil, true, true),
|
||||||
oldNode: nil,
|
oldNode: nil,
|
||||||
compareNode: makeNode(nil, false, false),
|
compareNode: makeNode(nil, false, false),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update with Spec.ConfigSource and Status.Config (old has none), enableNodeDynamicConfig disabled",
|
name: "update with Spec.ConfigSource and Status.Config (old has none)",
|
||||||
enableNodeDynamicConfig: false,
|
|
||||||
node: makeNode(nil, true, true),
|
node: makeNode(nil, true, true),
|
||||||
oldNode: makeNode(nil, false, false),
|
oldNode: makeNode(nil, false, false),
|
||||||
compareNode: makeNode(nil, false, true),
|
compareNode: makeNode(nil, false, true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update with Spec.ConfigSource and Status.Config (old has them), enableNodeDynamicConfig disabled",
|
name: "update with Spec.ConfigSource and Status.Config (old has them)",
|
||||||
enableNodeDynamicConfig: false,
|
|
||||||
node: makeNode(nil, true, true),
|
node: makeNode(nil, true, true),
|
||||||
oldNode: makeNode(nil, true, true),
|
oldNode: makeNode(nil, true, true),
|
||||||
compareNode: makeNode(nil, true, true),
|
compareNode: makeNode(nil, true, true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update with Spec.ConfigSource and Status.Config (old has Status.Config), enableNodeDynamicConfig disabled",
|
name: "update with Spec.ConfigSource and Status.Config (old has Status.Config)",
|
||||||
enableNodeDynamicConfig: false,
|
|
||||||
node: makeNode(nil, true, true),
|
node: makeNode(nil, true, true),
|
||||||
oldNode: makeNode(nil, false, true),
|
oldNode: makeNode(nil, false, true),
|
||||||
compareNode: 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),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
func() {
|
func() {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DynamicKubeletConfig, tc.enableNodeDynamicConfig)()
|
|
||||||
|
|
||||||
dropDisabledFields(tc.node, tc.oldNode)
|
dropDisabledFields(tc.node, tc.oldNode)
|
||||||
|
|
||||||
old := tc.oldNode.DeepCopy()
|
old := tc.oldNode.DeepCopy()
|
||||||
|
@ -476,31 +476,3 @@ func (g *Graph) DeleteVolumeAttachment(name string) {
|
|||||||
defer g.lock.Unlock()
|
defer g.lock.Unlock()
|
||||||
g.deleteVertex_locked(vaVertexType, "", name)
|
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
@ -25,11 +24,9 @@ import (
|
|||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
storagev1 "k8s.io/api/storage/v1"
|
storagev1 "k8s.io/api/storage/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
corev1informers "k8s.io/client-go/informers/core/v1"
|
corev1informers "k8s.io/client-go/informers/core/v1"
|
||||||
storageinformers "k8s.io/client-go/informers/storage/v1"
|
storageinformers "k8s.io/client-go/informers/storage/v1"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type graphPopulator struct {
|
type graphPopulator struct {
|
||||||
@ -49,15 +46,6 @@ func AddGraphEventHandlers(
|
|||||||
|
|
||||||
var hasSynced []cache.InformerSynced
|
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{
|
pods.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||||
AddFunc: g.addPod,
|
AddFunc: g.addPod,
|
||||||
UpdateFunc: g.updatePod,
|
UpdateFunc: g.updatePod,
|
||||||
@ -82,62 +70,6 @@ func AddGraphEventHandlers(
|
|||||||
go cache.WaitForNamedCacheSync("node_authorizer", wait.NeverStop, hasSynced...)
|
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{}) {
|
func (g *graphPopulator) addPod(obj interface{}) {
|
||||||
g.updatePod(nil, obj)
|
g.updatePod(nil, obj)
|
||||||
}
|
}
|
||||||
|
@ -343,74 +343,4 @@ func TestIndex(t *testing.T) {
|
|||||||
"configmap:ns/cm3": {"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"},
|
"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"},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ import (
|
|||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
storagev1 "k8s.io/api/storage/v1"
|
storagev1 "k8s.io/api/storage/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
@ -68,11 +67,6 @@ func TestAuthorizer(t *testing.T) {
|
|||||||
expect authorizer.Decision
|
expect authorizer.Decision
|
||||||
features featuregate.FeatureGate
|
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",
|
name: "allowed configmap",
|
||||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"},
|
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: ""},
|
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumes", Name: "pv0-pod0-node0-ns0", Namespace: ""},
|
||||||
expect: authorizer.DecisionAllow,
|
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",
|
name: "disallowed configmap",
|
||||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"},
|
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.AddPod(pod3)
|
||||||
|
|
||||||
g.SetNodeConfigMap("node1", "shared-configmap", "ns1")
|
|
||||||
g.SetNodeConfigMap("node2", "shared-configmap", "ns1")
|
|
||||||
g.SetNodeConfigMap("node3", "configmap", "ns1")
|
|
||||||
|
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
User user.Info
|
User user.Info
|
||||||
Secret string
|
Secret string
|
||||||
ConfigMap string
|
ConfigMap string
|
||||||
ExpectAllowed bool
|
Decision authorizer.Decision
|
||||||
}{
|
}{
|
||||||
{User: node1, ExpectAllowed: true, Secret: "node1-only"},
|
{User: node1, Decision: authorizer.DecisionAllow, Secret: "node1-only"},
|
||||||
{User: node1, ExpectAllowed: true, Secret: "node1-node2-only"},
|
{User: node1, Decision: authorizer.DecisionAllow, Secret: "node1-node2-only"},
|
||||||
{User: node1, ExpectAllowed: true, Secret: "shared-all"},
|
{User: node1, Decision: authorizer.DecisionAllow, Secret: "shared-all"},
|
||||||
|
|
||||||
{User: node2, ExpectAllowed: false, Secret: "node1-only"},
|
{User: node2, Decision: authorizer.DecisionNoOpinion, Secret: "node1-only"},
|
||||||
{User: node2, ExpectAllowed: true, Secret: "node1-node2-only"},
|
{User: node2, Decision: authorizer.DecisionAllow, Secret: "node1-node2-only"},
|
||||||
{User: node2, ExpectAllowed: true, Secret: "shared-all"},
|
{User: node2, Decision: authorizer.DecisionAllow, Secret: "shared-all"},
|
||||||
|
|
||||||
{User: node3, ExpectAllowed: false, Secret: "node1-only"},
|
{User: node3, Decision: authorizer.DecisionNoOpinion, Secret: "node1-only"},
|
||||||
{User: node3, ExpectAllowed: false, Secret: "node1-node2-only"},
|
{User: node3, Decision: authorizer.DecisionNoOpinion, Secret: "node1-node2-only"},
|
||||||
{User: node3, ExpectAllowed: true, Secret: "shared-all"},
|
{User: node3, Decision: authorizer.DecisionAllow, 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"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range testcases {
|
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")
|
t.Fatalf("test case must include a request for a Secret or ConfigMap")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decision == authorizer.DecisionAllow) != tc.ExpectAllowed {
|
if decision != tc.Decision {
|
||||||
t.Errorf("%d: expected %v, got %v", i, tc.ExpectAllowed, decision)
|
t.Errorf("%d: expected %v, got %v", i, tc.Decision, decision)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,11 +604,6 @@ func BenchmarkAuthorization(b *testing.B) {
|
|||||||
expect authorizer.Decision
|
expect authorizer.Decision
|
||||||
features featuregate.FeatureGate
|
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",
|
name: "allowed configmap",
|
||||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"},
|
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"},
|
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-shared", Namespace: "ns0"},
|
||||||
expect: authorizer.DecisionAllow,
|
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",
|
name: "disallowed configmap",
|
||||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"},
|
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) {
|
func populate(graph *Graph, nodes []*corev1.Node, pods []*corev1.Pod, pvs []*corev1.PersistentVolume, attachments []*storagev1.VolumeAttachment) {
|
||||||
p := &graphPopulator{}
|
p := &graphPopulator{}
|
||||||
p.graph = graph
|
p.graph = graph
|
||||||
for _, node := range nodes {
|
|
||||||
p.addNode(node)
|
|
||||||
}
|
|
||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
p.addPod(pod)
|
p.addPod(pod)
|
||||||
}
|
}
|
||||||
@ -830,19 +791,9 @@ func generate(opts *sampleDataOpts) ([]*corev1.Node, []*corev1.Pod, []*corev1.Pe
|
|||||||
attachments = append(attachments, attachment)
|
attachments = append(attachments, attachment)
|
||||||
}
|
}
|
||||||
|
|
||||||
name := fmt.Sprintf("%s-configmap", nodeName)
|
|
||||||
nodes = append(nodes, &corev1.Node{
|
nodes = append(nodes, &corev1.Node{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: nodeName},
|
ObjectMeta: metav1.ObjectMeta{Name: nodeName},
|
||||||
Spec: corev1.NodeSpec{
|
Spec: corev1.NodeSpec{},
|
||||||
ConfigSource: &corev1.NodeConfigSource{
|
|
||||||
ConfigMap: &corev1.ConfigMapNodeConfigSource{
|
|
||||||
Name: name,
|
|
||||||
Namespace: "ns0",
|
|
||||||
UID: types.UID(fmt.Sprintf("ns0-%s", name)),
|
|
||||||
KubeletConfigKey: "kubelet",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nodes, pods, pvs, attachments
|
return nodes, pods, pvs, attachments
|
||||||
|
@ -2413,7 +2413,7 @@ message NodeSpec {
|
|||||||
// +optional
|
// +optional
|
||||||
repeated Taint taints = 5;
|
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
|
||||||
optional NodeConfigSource configSource = 6;
|
optional NodeConfigSource configSource = 6;
|
||||||
|
|
||||||
|
@ -4898,7 +4898,7 @@ type NodeSpec struct {
|
|||||||
// +optional
|
// +optional
|
||||||
Taints []Taint `json:"taints,omitempty" protobuf:"bytes,5,opt,name=taints"`
|
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
|
// +optional
|
||||||
ConfigSource *NodeConfigSource `json:"configSource,omitempty" protobuf:"bytes,6,opt,name=configSource"`
|
ConfigSource *NodeConfigSource `json:"configSource,omitempty" protobuf:"bytes,6,opt,name=configSource"`
|
||||||
|
|
||||||
|
@ -1189,7 +1189,7 @@ var map_NodeSpec = map[string]string{
|
|||||||
"providerID": "ID of the node assigned by the cloud provider in the format: <ProviderName>://<ProviderSpecificNodeID>",
|
"providerID": "ID of the node assigned by the cloud provider in the format: <ProviderName>://<ProviderSpecificNodeID>",
|
||||||
"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",
|
"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.",
|
"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",
|
"externalID": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,11 +33,8 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
|
||||||
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/test/integration/framework"
|
"k8s.io/kubernetes/test/integration/framework"
|
||||||
"k8s.io/utils/pointer"
|
"k8s.io/utils/pointer"
|
||||||
)
|
)
|
||||||
@ -52,9 +49,6 @@ func TestNodeAuthorizer(t *testing.T) {
|
|||||||
tokenNode2 = "node2-token"
|
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")
|
tokenFile, err := os.CreateTemp("", "kubeconfig")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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 {
|
if _, err := superuserClient.CoreV1().ConfigMaps("ns").Create(context.TODO(), &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "myconfigmap"}}, metav1.CreateOptions{}); err != nil {
|
||||||
t.Fatal(err)
|
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"
|
pvName := "mypv"
|
||||||
if _, err := superuserClientExternal.StorageV1().VolumeAttachments().Create(context.TODO(), &storagev1.VolumeAttachment{
|
if _, err := superuserClientExternal.StorageV1().VolumeAttachments().Create(context.TODO(), &storagev1.VolumeAttachment{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "myattachment"},
|
ObjectMeta: metav1.ObjectMeta{Name: "myattachment"},
|
||||||
@ -160,12 +151,6 @@ func TestNodeAuthorizer(t *testing.T) {
|
|||||||
return err
|
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 {
|
getPVC := func(client clientset.Interface) func() error {
|
||||||
return func() error {
|
return func() error {
|
||||||
_, err := client.CoreV1().PersistentVolumeClaims("ns").Get(context.TODO(), "mypvc", metav1.GetOptions{})
|
_, err := client.CoreV1().PersistentVolumeClaims("ns").Get(context.TODO(), "mypvc", metav1.GetOptions{})
|
||||||
@ -260,34 +245,6 @@ func TestNodeAuthorizer(t *testing.T) {
|
|||||||
return err
|
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 {
|
updateNode2Status := func(client clientset.Interface) func() error {
|
||||||
return func() error {
|
return func() error {
|
||||||
_, err := client.CoreV1().Nodes().UpdateStatus(context.TODO(), &corev1.Node{
|
_, err := client.CoreV1().Nodes().UpdateStatus(context.TODO(), &corev1.Node{
|
||||||
@ -578,20 +535,6 @@ func TestNodeAuthorizer(t *testing.T) {
|
|||||||
|
|
||||||
// create node2 again
|
// create node2 again
|
||||||
expectAllowed(t, createNode2(node2Client))
|
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
|
// clean up node2
|
||||||
expectAllowed(t, deleteNode2(superuserClient))
|
expectAllowed(t, deleteNode2(superuserClient))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user