mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-06 10:43:56 +00:00
Merge pull request #126318 from hoskeri/node-self-register-continue-on-forbidden
node self-register continue if CREATE is 403.
This commit is contained in:
commit
36fafafdb0
@ -219,6 +219,13 @@ const (
|
|||||||
// Remove in v1.33
|
// Remove in v1.33
|
||||||
AllowInsecureKubeletCertificateSigningRequests featuregate.Feature = "AllowInsecureKubeletCertificateSigningRequests"
|
AllowInsecureKubeletCertificateSigningRequests featuregate.Feature = "AllowInsecureKubeletCertificateSigningRequests"
|
||||||
|
|
||||||
|
// owner: @hoskeri
|
||||||
|
// Deprecated: v1.32
|
||||||
|
//
|
||||||
|
// Restores previous behavior where Kubelet fails self registration if node create returns 403 Forbidden.
|
||||||
|
// Remove in v1.34
|
||||||
|
KubeletRegistrationGetOnExistsOnly featuregate.Feature = "KubeletRegistrationGetOnExistsOnly"
|
||||||
|
|
||||||
// owner: @HirazawaUi
|
// owner: @HirazawaUi
|
||||||
// kep: http://kep.k8s.io/4004
|
// kep: http://kep.k8s.io/4004
|
||||||
// Deprecated: v1.29 (default off)
|
// Deprecated: v1.29 (default off)
|
||||||
|
@ -443,4 +443,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
|
|||||||
ImageVolume: {
|
ImageVolume: {
|
||||||
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
|
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
|
||||||
},
|
},
|
||||||
|
KubeletRegistrationGetOnExistsOnly: {
|
||||||
|
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Deprecated},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,14 @@ 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/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
cloudproviderapi "k8s.io/cloud-provider/api"
|
cloudproviderapi "k8s.io/cloud-provider/api"
|
||||||
nodeutil "k8s.io/component-helpers/node/util"
|
nodeutil "k8s.io/component-helpers/node/util"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
kubeletapis "k8s.io/kubelet/pkg/apis"
|
kubeletapis "k8s.io/kubelet/pkg/apis"
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/events"
|
"k8s.io/kubernetes/pkg/kubelet/events"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/nodestatus"
|
"k8s.io/kubernetes/pkg/kubelet/nodestatus"
|
||||||
taintutil "k8s.io/kubernetes/pkg/util/taints"
|
taintutil "k8s.io/kubernetes/pkg/util/taints"
|
||||||
@ -91,7 +93,16 @@ func (kl *Kubelet) tryRegisterWithAPIServer(node *v1.Node) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !apierrors.IsAlreadyExists(err) {
|
switch {
|
||||||
|
case apierrors.IsAlreadyExists(err):
|
||||||
|
// Node already exists, proceed to reconcile node.
|
||||||
|
case apierrors.IsForbidden(err):
|
||||||
|
// Creating nodes is forbidden, but node may still exist, attempt to get the node.
|
||||||
|
if utilfeature.DefaultFeatureGate.Enabled(features.KubeletRegistrationGetOnExistsOnly) {
|
||||||
|
klog.ErrorS(err, "Unable to register node with API server, reason is forbidden", "node", klog.KObj(node))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
default:
|
||||||
klog.ErrorS(err, "Unable to register node with API server", "node", klog.KObj(node))
|
klog.ErrorS(err, "Unable to register node with API server", "node", klog.KObj(node))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -101,6 +112,7 @@ func (kl *Kubelet) tryRegisterWithAPIServer(node *v1.Node) bool {
|
|||||||
klog.ErrorS(err, "Unable to register node with API server, error getting existing node", "node", klog.KObj(node))
|
klog.ErrorS(err, "Unable to register node with API server, error getting existing node", "node", klog.KObj(node))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if existingNode == nil {
|
if existingNode == nil {
|
||||||
klog.InfoS("Unable to register node with API server, no node instance returned", "node", klog.KObj(node))
|
klog.InfoS("Unable to register node with API server, no node instance returned", "node", klog.KObj(node))
|
||||||
return false
|
return false
|
||||||
|
@ -45,13 +45,17 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/rand"
|
"k8s.io/apimachinery/pkg/util/rand"
|
||||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
|
utilversion "k8s.io/apimachinery/pkg/util/version"
|
||||||
"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"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
"k8s.io/component-base/version"
|
"k8s.io/component-base/version"
|
||||||
kubeletapis "k8s.io/kubelet/pkg/apis"
|
kubeletapis "k8s.io/kubelet/pkg/apis"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing"
|
cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/cm"
|
"k8s.io/kubernetes/pkg/kubelet/cm"
|
||||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||||
@ -1386,6 +1390,10 @@ func TestTryRegisterWithApiServer(t *testing.T) {
|
|||||||
ErrStatus: metav1.Status{Reason: metav1.StatusReasonConflict},
|
ErrStatus: metav1.Status{Reason: metav1.StatusReasonConflict},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forbidden := &apierrors.StatusError{
|
||||||
|
ErrStatus: metav1.Status{Reason: metav1.StatusReasonForbidden},
|
||||||
|
}
|
||||||
|
|
||||||
newNode := func(cmad bool) *v1.Node {
|
newNode := func(cmad bool) *v1.Node {
|
||||||
node := &v1.Node{
|
node := &v1.Node{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1418,6 +1426,7 @@ func TestTryRegisterWithApiServer(t *testing.T) {
|
|||||||
expectedResult bool
|
expectedResult bool
|
||||||
expectedActions int
|
expectedActions int
|
||||||
testSavedNode bool
|
testSavedNode bool
|
||||||
|
getOnForbiddenDisabled bool
|
||||||
savedNodeIndex int
|
savedNodeIndex int
|
||||||
savedNodeCMAD bool
|
savedNodeCMAD bool
|
||||||
}{
|
}{
|
||||||
@ -1435,6 +1444,25 @@ func TestTryRegisterWithApiServer(t *testing.T) {
|
|||||||
expectedResult: true,
|
expectedResult: true,
|
||||||
expectedActions: 2,
|
expectedActions: 2,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "success case - existing node - create forbidden - no change in CMAD",
|
||||||
|
newNode: newNode(true),
|
||||||
|
createError: forbidden,
|
||||||
|
existingNode: newNode(true),
|
||||||
|
expectedResult: true,
|
||||||
|
expectedActions: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "success case - existing node - create forbidden - CMAD disabled",
|
||||||
|
newNode: newNode(false),
|
||||||
|
createError: forbidden,
|
||||||
|
existingNode: newNode(true),
|
||||||
|
expectedResult: true,
|
||||||
|
expectedActions: 3,
|
||||||
|
testSavedNode: true,
|
||||||
|
savedNodeIndex: 2,
|
||||||
|
savedNodeCMAD: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "success case - existing node - CMAD disabled",
|
name: "success case - existing node - CMAD disabled",
|
||||||
newNode: newNode(false),
|
newNode: newNode(false),
|
||||||
@ -1464,6 +1492,14 @@ func TestTryRegisterWithApiServer(t *testing.T) {
|
|||||||
expectedResult: false,
|
expectedResult: false,
|
||||||
expectedActions: 1,
|
expectedActions: 1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "create failed with forbidden - get-on-forbidden feature is disabled",
|
||||||
|
newNode: newNode(false),
|
||||||
|
getOnForbiddenDisabled: true,
|
||||||
|
createError: forbidden,
|
||||||
|
expectedResult: false,
|
||||||
|
expectedActions: 1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "get existing node failed",
|
name: "get existing node failed",
|
||||||
newNode: newNode(false),
|
newNode: newNode(false),
|
||||||
@ -1484,6 +1520,11 @@ func TestTryRegisterWithApiServer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
if tc.getOnForbiddenDisabled {
|
||||||
|
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, utilversion.MustParse("1.32"))
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.KubeletRegistrationGetOnExistsOnly, true)
|
||||||
|
}
|
||||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled is a don't-care for this test */)
|
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled is a don't-care for this test */)
|
||||||
defer testKubelet.Cleanup()
|
defer testKubelet.Cleanup()
|
||||||
kubelet := testKubelet.kubelet
|
kubelet := testKubelet.kubelet
|
||||||
@ -1533,6 +1574,7 @@ func TestTryRegisterWithApiServer(t *testing.T) {
|
|||||||
actualCMAD, _ := strconv.ParseBool(savedNode.Annotations[util.ControllerManagedAttachAnnotation])
|
actualCMAD, _ := strconv.ParseBool(savedNode.Annotations[util.ControllerManagedAttachAnnotation])
|
||||||
assert.Equal(t, tc.savedNodeCMAD, actualCMAD, "test [%s]", tc.name)
|
assert.Equal(t, tc.savedNodeCMAD, actualCMAD, "test [%s]", tc.name)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +362,12 @@
|
|||||||
lockToDefault: false
|
lockToDefault: false
|
||||||
preRelease: Alpha
|
preRelease: Alpha
|
||||||
version: "1.27"
|
version: "1.27"
|
||||||
|
- name: KubeletRegistrationGetOnExistsOnly
|
||||||
|
versionedSpecs:
|
||||||
|
- default: false
|
||||||
|
lockToDefault: false
|
||||||
|
preRelease: Deprecated
|
||||||
|
version: "1.32"
|
||||||
- name: KubeletSeparateDiskGC
|
- name: KubeletSeparateDiskGC
|
||||||
versionedSpecs:
|
versionedSpecs:
|
||||||
- default: false
|
- default: false
|
||||||
|
Loading…
Reference in New Issue
Block a user