Merge pull request #95382 from neolit123/1.20-deprecate-master-label

kubeadm: deprecate the "node-role.kubernetes.io/master" label / taint
This commit is contained in:
Kubernetes Prow Robot 2020-11-11 06:06:10 -08:00 committed by GitHub
commit 6b24a5796c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 209 additions and 111 deletions

View File

@ -28,6 +28,7 @@ import (
"k8s.io/klog/v2" "k8s.io/klog/v2"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/features" "k8s.io/kubernetes/cmd/kubeadm/app/features"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade" "k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight" "k8s.io/kubernetes/cmd/kubeadm/app/preflight"
@ -163,6 +164,13 @@ func runApply(flags *applyFlags, args []string) error {
return errors.Wrap(err, "[upgrade/apply] FATAL") return errors.Wrap(err, "[upgrade/apply] FATAL")
} }
// TODO: https://github.com/kubernetes/kubeadm/issues/2200
fmt.Printf("[upgrade/postupgrade] Applying label %s='' to Nodes with label %s='' (deprecated)\n",
kubeadmconstants.LabelNodeRoleControlPlane, kubeadmconstants.LabelNodeRoleOldControlPlane)
if err := upgrade.LabelOldControlPlaneNodes(client); err != nil {
return err
}
// Upgrade RBAC rules and addons. // Upgrade RBAC rules and addons.
klog.V(1).Infoln("[upgrade/postupgrade] upgrading RBAC rules and addons") klog.V(1).Infoln("[upgrade/postupgrade] upgrading RBAC rules and addons")
if err := upgrade.PerformPostUpgradeTasks(client, cfg, flags.dryRun); err != nil { if err := upgrade.PerformPostUpgradeTasks(client, cfg, flags.dryRun); err != nil {

View File

@ -225,9 +225,12 @@ const (
// CertificateKeySize specifies the size of the key used to encrypt certificates on uploadcerts phase // CertificateKeySize specifies the size of the key used to encrypt certificates on uploadcerts phase
CertificateKeySize = 32 CertificateKeySize = 32
// LabelNodeRoleMaster specifies that a node is a control-plane // LabelNodeRoleOldControlPlane specifies that a node hosts control-plane components
// This is a duplicate definition of the constant in pkg/controller/service/controller.go // DEPRECATED: https://github.com/kubernetes/kubeadm/issues/2200
LabelNodeRoleMaster = "node-role.kubernetes.io/master" LabelNodeRoleOldControlPlane = "node-role.kubernetes.io/master"
// LabelNodeRoleControlPlane specifies that a node hosts control-plane components
LabelNodeRoleControlPlane = "node-role.kubernetes.io/control-plane"
// AnnotationKubeadmCRISocket specifies the annotation kubeadm uses to preserve the crisocket information given to kubeadm at // AnnotationKubeadmCRISocket specifies the annotation kubeadm uses to preserve the crisocket information given to kubeadm at
// init/join time for use later. kubeadm annotates the node object with this information // init/join time for use later. kubeadm annotates the node object with this information
@ -414,15 +417,29 @@ const (
) )
var ( var (
// OldControlPlaneTaint is the taint to apply on the PodSpec for being able to run that Pod on the control-plane
// DEPRECATED: https://github.com/kubernetes/kubeadm/issues/2200
OldControlPlaneTaint = v1.Taint{
Key: LabelNodeRoleOldControlPlane,
Effect: v1.TaintEffectNoSchedule,
}
// OldControlPlaneToleration is the toleration to apply on the PodSpec for being able to run that Pod on the control-plane
// DEPRECATED: https://github.com/kubernetes/kubeadm/issues/2200
OldControlPlaneToleration = v1.Toleration{
Key: LabelNodeRoleOldControlPlane,
Effect: v1.TaintEffectNoSchedule,
}
// ControlPlaneTaint is the taint to apply on the PodSpec for being able to run that Pod on the control-plane // ControlPlaneTaint is the taint to apply on the PodSpec for being able to run that Pod on the control-plane
ControlPlaneTaint = v1.Taint{ ControlPlaneTaint = v1.Taint{
Key: LabelNodeRoleMaster, Key: LabelNodeRoleControlPlane,
Effect: v1.TaintEffectNoSchedule, Effect: v1.TaintEffectNoSchedule,
} }
// ControlPlaneToleration is the toleration to apply on the PodSpec for being able to run that Pod on the control-plane // ControlPlaneToleration is the toleration to apply on the PodSpec for being able to run that Pod on the control-plane
ControlPlaneToleration = v1.Toleration{ ControlPlaneToleration = v1.Toleration{
Key: LabelNodeRoleMaster, Key: LabelNodeRoleControlPlane,
Effect: v1.TaintEffectNoSchedule, Effect: v1.TaintEffectNoSchedule,
} }

View File

@ -135,7 +135,7 @@ func kubeDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interfa
dnsDeploymentBytes, err := kubeadmutil.ParseTemplate(KubeDNSDeployment, dnsDeploymentBytes, err := kubeadmutil.ParseTemplate(KubeDNSDeployment,
struct { struct {
DeploymentName, KubeDNSImage, DNSMasqImage, SidecarImage, DNSBindAddr, DNSProbeAddr, DNSDomain, ControlPlaneTaintKey string DeploymentName, KubeDNSImage, DNSMasqImage, SidecarImage, DNSBindAddr, DNSProbeAddr, DNSDomain, OldControlPlaneTaintKey, ControlPlaneTaintKey string
Replicas *int32 Replicas *int32
}{ }{
DeploymentName: kubeadmconstants.KubeDNSDeploymentName, DeploymentName: kubeadmconstants.KubeDNSDeploymentName,
@ -145,7 +145,9 @@ func kubeDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interfa
DNSBindAddr: dnsBindAddr, DNSBindAddr: dnsBindAddr,
DNSProbeAddr: dnsProbeAddr, DNSProbeAddr: dnsProbeAddr,
DNSDomain: cfg.Networking.DNSDomain, DNSDomain: cfg.Networking.DNSDomain,
ControlPlaneTaintKey: kubeadmconstants.LabelNodeRoleMaster, // TODO: https://github.com/kubernetes/kubeadm/issues/2200
OldControlPlaneTaintKey: kubeadmconstants.LabelNodeRoleOldControlPlane,
ControlPlaneTaintKey: kubeadmconstants.LabelNodeRoleControlPlane,
Replicas: replicas, Replicas: replicas,
}) })
if err != nil { if err != nil {
@ -196,12 +198,14 @@ func createKubeDNSAddon(deploymentBytes, serviceBytes []byte, client clientset.I
func coreDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface, replicas *int32) error { func coreDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface, replicas *int32) error {
// Get the YAML manifest // Get the YAML manifest
coreDNSDeploymentBytes, err := kubeadmutil.ParseTemplate(CoreDNSDeployment, struct { coreDNSDeploymentBytes, err := kubeadmutil.ParseTemplate(CoreDNSDeployment, struct {
DeploymentName, Image, ControlPlaneTaintKey string DeploymentName, Image, OldControlPlaneTaintKey, ControlPlaneTaintKey string
Replicas *int32 Replicas *int32
}{ }{
DeploymentName: kubeadmconstants.CoreDNSDeploymentName, DeploymentName: kubeadmconstants.CoreDNSDeploymentName,
Image: images.GetDNSImage(cfg, kubeadmconstants.CoreDNSImageName), Image: images.GetDNSImage(cfg, kubeadmconstants.CoreDNSImageName),
ControlPlaneTaintKey: kubeadmconstants.LabelNodeRoleMaster, // TODO: https://github.com/kubernetes/kubeadm/issues/2200
OldControlPlaneTaintKey: kubeadmconstants.LabelNodeRoleOldControlPlane,
ControlPlaneTaintKey: kubeadmconstants.LabelNodeRoleControlPlane,
Replicas: replicas, Replicas: replicas,
}) })
if err != nil { if err != nil {

View File

@ -102,7 +102,7 @@ func TestCompileManifests(t *testing.T) {
name: "KubeDNSDeployment manifest", name: "KubeDNSDeployment manifest",
manifest: KubeDNSDeployment, manifest: KubeDNSDeployment,
data: struct { data: struct {
DeploymentName, KubeDNSImage, DNSMasqImage, SidecarImage, DNSBindAddr, DNSProbeAddr, DNSDomain, ControlPlaneTaintKey string DeploymentName, KubeDNSImage, DNSMasqImage, SidecarImage, DNSBindAddr, DNSProbeAddr, DNSDomain, OldControlPlaneTaintKey, ControlPlaneTaintKey string
Replicas *int32 Replicas *int32
}{ }{
DeploymentName: "foo", DeploymentName: "foo",
@ -112,6 +112,7 @@ func TestCompileManifests(t *testing.T) {
DNSBindAddr: "foo", DNSBindAddr: "foo",
DNSProbeAddr: "foo", DNSProbeAddr: "foo",
DNSDomain: "foo", DNSDomain: "foo",
OldControlPlaneTaintKey: "foo",
ControlPlaneTaintKey: "foo", ControlPlaneTaintKey: "foo",
Replicas: &replicas, Replicas: &replicas,
}, },
@ -127,11 +128,12 @@ func TestCompileManifests(t *testing.T) {
name: "CoreDNSDeployment manifest", name: "CoreDNSDeployment manifest",
manifest: CoreDNSDeployment, manifest: CoreDNSDeployment,
data: struct { data: struct {
DeploymentName, Image, ControlPlaneTaintKey string DeploymentName, Image, OldControlPlaneTaintKey, ControlPlaneTaintKey string
Replicas *int32 Replicas *int32
}{ }{
DeploymentName: "foo", DeploymentName: "foo",
Image: "foo", Image: "foo",
OldControlPlaneTaintKey: "foo",
ControlPlaneTaintKey: "foo", ControlPlaneTaintKey: "foo",
Replicas: &replicas, Replicas: &replicas,
}, },
@ -506,7 +508,7 @@ func TestDeploymentsHaveSystemClusterCriticalPriorityClassName(t *testing.T) {
name: "KubeDNSDeployment", name: "KubeDNSDeployment",
manifest: KubeDNSDeployment, manifest: KubeDNSDeployment,
data: struct { data: struct {
DeploymentName, KubeDNSImage, DNSMasqImage, SidecarImage, DNSBindAddr, DNSProbeAddr, DNSDomain, ControlPlaneTaintKey string DeploymentName, KubeDNSImage, DNSMasqImage, SidecarImage, DNSBindAddr, DNSProbeAddr, DNSDomain, OldControlPlaneTaintKey, ControlPlaneTaintKey string
Replicas *int32 Replicas *int32
}{ }{
DeploymentName: "foo", DeploymentName: "foo",
@ -516,6 +518,7 @@ func TestDeploymentsHaveSystemClusterCriticalPriorityClassName(t *testing.T) {
DNSBindAddr: "foo", DNSBindAddr: "foo",
DNSProbeAddr: "foo", DNSProbeAddr: "foo",
DNSDomain: "foo", DNSDomain: "foo",
OldControlPlaneTaintKey: "foo",
ControlPlaneTaintKey: "foo", ControlPlaneTaintKey: "foo",
Replicas: &replicas, Replicas: &replicas,
}, },
@ -524,11 +527,12 @@ func TestDeploymentsHaveSystemClusterCriticalPriorityClassName(t *testing.T) {
name: "CoreDNSDeployment", name: "CoreDNSDeployment",
manifest: CoreDNSDeployment, manifest: CoreDNSDeployment,
data: struct { data: struct {
DeploymentName, Image, ControlPlaneTaintKey, CoreDNSConfigMapName string DeploymentName, Image, OldControlPlaneTaintKey, ControlPlaneTaintKey, CoreDNSConfigMapName string
Replicas *int32 Replicas *int32
}{ }{
DeploymentName: "foo", DeploymentName: "foo",
Image: "foo", Image: "foo",
OldControlPlaneTaintKey: "foo",
ControlPlaneTaintKey: "foo", ControlPlaneTaintKey: "foo",
CoreDNSConfigMapName: "foo", CoreDNSConfigMapName: "foo",
Replicas: &replicas, Replicas: &replicas,

View File

@ -170,6 +170,8 @@ spec:
tolerations: tolerations:
- key: CriticalAddonsOnly - key: CriticalAddonsOnly
operator: Exists operator: Exists
- key: {{ .OldControlPlaneTaintKey }}
effect: NoSchedule
- key: {{ .ControlPlaneTaintKey }} - key: {{ .ControlPlaneTaintKey }}
effect: NoSchedule effect: NoSchedule
` `
@ -238,6 +240,8 @@ spec:
tolerations: tolerations:
- key: CriticalAddonsOnly - key: CriticalAddonsOnly
operator: Exists operator: Exists
- key: {{ .OldControlPlaneTaintKey }}
effect: NoSchedule
- key: {{ .ControlPlaneTaintKey }} - key: {{ .ControlPlaneTaintKey }}
effect: NoSchedule effect: NoSchedule
nodeSelector: nodeSelector:

View File

@ -28,7 +28,9 @@ import (
// MarkControlPlane taints the control-plane and sets the control-plane label // MarkControlPlane taints the control-plane and sets the control-plane label
func MarkControlPlane(client clientset.Interface, controlPlaneName string, taints []v1.Taint) error { func MarkControlPlane(client clientset.Interface, controlPlaneName string, taints []v1.Taint) error {
fmt.Printf("[mark-control-plane] Marking the node %s as control-plane by adding the label \"%s=''\"\n", controlPlaneName, constants.LabelNodeRoleMaster) // TODO: https://github.com/kubernetes/kubeadm/issues/2200
fmt.Printf("[mark-control-plane] Marking the node %s as control-plane by adding the labels \"%s=''\" and \"%s='' (deprecated)\"\n",
controlPlaneName, constants.LabelNodeRoleOldControlPlane, constants.LabelNodeRoleControlPlane)
if len(taints) > 0 { if len(taints) > 0 {
taintStrs := []string{} taintStrs := []string{}
@ -54,7 +56,9 @@ func taintExists(taint v1.Taint, taints []v1.Taint) bool {
} }
func markControlPlaneNode(n *v1.Node, taints []v1.Taint) { func markControlPlaneNode(n *v1.Node, taints []v1.Taint) {
n.ObjectMeta.Labels[constants.LabelNodeRoleMaster] = "" // TODO: https://github.com/kubernetes/kubeadm/issues/2200
n.ObjectMeta.Labels[constants.LabelNodeRoleOldControlPlane] = ""
n.ObjectMeta.Labels[constants.LabelNodeRoleControlPlane] = ""
for _, nt := range n.Spec.Taints { for _, nt := range n.Spec.Taints {
if !taintExists(nt, taints) { if !taintExists(nt, taints) {

View File

@ -38,49 +38,58 @@ func TestMarkControlPlane(t *testing.T) {
// future. // future.
tests := []struct { tests := []struct {
name string name string
existingLabel string existingLabels []string
existingTaints []v1.Taint existingTaints []v1.Taint
newTaints []v1.Taint newTaints []v1.Taint
expectedPatch string expectedPatch string
}{ }{
{ {
name: "control-plane label and taint missing", name: "control-plane label and taint missing",
existingLabel: "", existingLabels: []string{""},
existingTaints: nil, existingTaints: nil,
newTaints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, newTaints: []v1.Taint{kubeadmconstants.OldControlPlaneTaint},
expectedPatch: `{"metadata":{"labels":{"node-role.kubernetes.io/master":""}},"spec":{"taints":[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"}]}}`, expectedPatch: `{"metadata":{"labels":{"node-role.kubernetes.io/control-plane":"","node-role.kubernetes.io/master":""}},"spec":{"taints":[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"}]}}`,
}, },
{ {
name: "control-plane label and taint missing but taint not wanted", name: "control-plane label and taint missing but taint not wanted",
existingLabel: "", existingLabels: []string{""},
existingTaints: nil, existingTaints: nil,
newTaints: nil, newTaints: nil,
expectedPatch: `{"metadata":{"labels":{"node-role.kubernetes.io/master":""}}}`, expectedPatch: `{"metadata":{"labels":{"node-role.kubernetes.io/control-plane":"","node-role.kubernetes.io/master":""}}}`,
}, },
{ {
name: "control-plane label missing", name: "control-plane label missing",
existingLabel: "", existingLabels: []string{""},
existingTaints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, existingTaints: []v1.Taint{kubeadmconstants.OldControlPlaneTaint},
newTaints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, newTaints: []v1.Taint{kubeadmconstants.OldControlPlaneTaint},
expectedPatch: `{"metadata":{"labels":{"node-role.kubernetes.io/master":""}}}`, expectedPatch: `{"metadata":{"labels":{"node-role.kubernetes.io/control-plane":"","node-role.kubernetes.io/master":""}}}`,
}, },
{ {
name: "control-plane taint missing", name: "control-plane taint missing",
existingLabel: kubeadmconstants.LabelNodeRoleMaster, existingLabels: []string{
kubeadmconstants.LabelNodeRoleOldControlPlane,
kubeadmconstants.LabelNodeRoleControlPlane,
},
existingTaints: nil, existingTaints: nil,
newTaints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, newTaints: []v1.Taint{kubeadmconstants.OldControlPlaneTaint},
expectedPatch: `{"spec":{"taints":[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"}]}}`, expectedPatch: `{"spec":{"taints":[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"}]}}`,
}, },
{ {
name: "nothing missing", name: "nothing missing",
existingLabel: kubeadmconstants.LabelNodeRoleMaster, existingLabels: []string{
existingTaints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, kubeadmconstants.LabelNodeRoleOldControlPlane,
newTaints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, kubeadmconstants.LabelNodeRoleControlPlane,
},
existingTaints: []v1.Taint{kubeadmconstants.OldControlPlaneTaint},
newTaints: []v1.Taint{kubeadmconstants.OldControlPlaneTaint},
expectedPatch: `{}`, expectedPatch: `{}`,
}, },
{ {
name: "has taint and no new taints wanted", name: "has taint and no new taints wanted",
existingLabel: kubeadmconstants.LabelNodeRoleMaster, existingLabels: []string{
kubeadmconstants.LabelNodeRoleOldControlPlane,
kubeadmconstants.LabelNodeRoleControlPlane,
},
existingTaints: []v1.Taint{ existingTaints: []v1.Taint{
{ {
Key: "node.cloudprovider.kubernetes.io/uninitialized", Key: "node.cloudprovider.kubernetes.io/uninitialized",
@ -92,14 +101,17 @@ func TestMarkControlPlane(t *testing.T) {
}, },
{ {
name: "has taint and should merge with wanted taint", name: "has taint and should merge with wanted taint",
existingLabel: kubeadmconstants.LabelNodeRoleMaster, existingLabels: []string{
kubeadmconstants.LabelNodeRoleOldControlPlane,
kubeadmconstants.LabelNodeRoleControlPlane,
},
existingTaints: []v1.Taint{ existingTaints: []v1.Taint{
{ {
Key: "node.cloudprovider.kubernetes.io/uninitialized", Key: "node.cloudprovider.kubernetes.io/uninitialized",
Effect: v1.TaintEffectNoSchedule, Effect: v1.TaintEffectNoSchedule,
}, },
}, },
newTaints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, newTaints: []v1.Taint{kubeadmconstants.OldControlPlaneTaint},
expectedPatch: `{"spec":{"taints":[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"},{"effect":"NoSchedule","key":"node.cloudprovider.kubernetes.io/uninitialized"}]}}`, expectedPatch: `{"spec":{"taints":[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"},{"effect":"NoSchedule","key":"node.cloudprovider.kubernetes.io/uninitialized"}]}}`,
}, },
} }
@ -116,8 +128,8 @@ func TestMarkControlPlane(t *testing.T) {
}, },
} }
if tc.existingLabel != "" { for _, label := range tc.existingLabels {
controlPlaneNode.ObjectMeta.Labels[tc.existingLabel] = "" controlPlaneNode.ObjectMeta.Labels[label] = ""
} }
if tc.existingTaints != nil { if tc.existingTaints != nil {

View File

@ -85,21 +85,22 @@ func mutatePodSpec(mutators map[string][]PodSpecMutatorFunc, name string, podSpe
// addNodeSelectorToPodSpec makes Pod require to be scheduled on a node marked with the control-plane label // addNodeSelectorToPodSpec makes Pod require to be scheduled on a node marked with the control-plane label
func addNodeSelectorToPodSpec(podSpec *v1.PodSpec) { func addNodeSelectorToPodSpec(podSpec *v1.PodSpec) {
if podSpec.NodeSelector == nil { if podSpec.NodeSelector == nil {
podSpec.NodeSelector = map[string]string{kubeadmconstants.LabelNodeRoleMaster: ""} podSpec.NodeSelector = map[string]string{kubeadmconstants.LabelNodeRoleOldControlPlane: ""}
return return
} }
podSpec.NodeSelector[kubeadmconstants.LabelNodeRoleMaster] = "" podSpec.NodeSelector[kubeadmconstants.LabelNodeRoleOldControlPlane] = ""
} }
// setControlPlaneTolerationOnPodSpec makes the Pod tolerate the control-plane taint // setControlPlaneTolerationOnPodSpec makes the Pod tolerate the control-plane taint
func setControlPlaneTolerationOnPodSpec(podSpec *v1.PodSpec) { func setControlPlaneTolerationOnPodSpec(podSpec *v1.PodSpec) {
if podSpec.Tolerations == nil { if podSpec.Tolerations == nil {
podSpec.Tolerations = []v1.Toleration{kubeadmconstants.ControlPlaneToleration} // TODO: https://github.com/kubernetes/kubeadm/issues/2200
podSpec.Tolerations = []v1.Toleration{kubeadmconstants.OldControlPlaneToleration}
return return
} }
podSpec.Tolerations = append(podSpec.Tolerations, kubeadmconstants.ControlPlaneToleration) podSpec.Tolerations = append(podSpec.Tolerations, kubeadmconstants.OldControlPlaneToleration)
} }
// setHostIPOnPodSpec sets the environment variable HOST_IP using downward API // setHostIPOnPodSpec sets the environment variable HOST_IP using downward API

View File

@ -66,10 +66,10 @@ func TestMutatePodSpec(t *testing.T) {
}, },
NodeSelector: map[string]string{ NodeSelector: map[string]string{
kubeadmconstants.LabelNodeRoleMaster: "", kubeadmconstants.LabelNodeRoleOldControlPlane: "",
}, },
Tolerations: []v1.Toleration{ Tolerations: []v1.Toleration{
kubeadmconstants.ControlPlaneToleration, kubeadmconstants.OldControlPlaneToleration,
}, },
DNSPolicy: v1.DNSClusterFirstWithHostNet, DNSPolicy: v1.DNSClusterFirstWithHostNet,
}, },
@ -80,10 +80,10 @@ func TestMutatePodSpec(t *testing.T) {
podSpec: &v1.PodSpec{}, podSpec: &v1.PodSpec{},
expected: v1.PodSpec{ expected: v1.PodSpec{
NodeSelector: map[string]string{ NodeSelector: map[string]string{
kubeadmconstants.LabelNodeRoleMaster: "", kubeadmconstants.LabelNodeRoleOldControlPlane: "",
}, },
Tolerations: []v1.Toleration{ Tolerations: []v1.Toleration{
kubeadmconstants.ControlPlaneToleration, kubeadmconstants.OldControlPlaneToleration,
}, },
DNSPolicy: v1.DNSClusterFirstWithHostNet, DNSPolicy: v1.DNSClusterFirstWithHostNet,
}, },
@ -94,10 +94,10 @@ func TestMutatePodSpec(t *testing.T) {
podSpec: &v1.PodSpec{}, podSpec: &v1.PodSpec{},
expected: v1.PodSpec{ expected: v1.PodSpec{
NodeSelector: map[string]string{ NodeSelector: map[string]string{
kubeadmconstants.LabelNodeRoleMaster: "", kubeadmconstants.LabelNodeRoleOldControlPlane: "",
}, },
Tolerations: []v1.Toleration{ Tolerations: []v1.Toleration{
kubeadmconstants.ControlPlaneToleration, kubeadmconstants.OldControlPlaneToleration,
}, },
DNSPolicy: v1.DNSClusterFirstWithHostNet, DNSPolicy: v1.DNSClusterFirstWithHostNet,
}, },
@ -126,7 +126,7 @@ func TestAddNodeSelectorToPodSpec(t *testing.T) {
podSpec: &v1.PodSpec{}, podSpec: &v1.PodSpec{},
expected: v1.PodSpec{ expected: v1.PodSpec{
NodeSelector: map[string]string{ NodeSelector: map[string]string{
kubeadmconstants.LabelNodeRoleMaster: "", kubeadmconstants.LabelNodeRoleOldControlPlane: "",
}, },
}, },
}, },
@ -140,7 +140,7 @@ func TestAddNodeSelectorToPodSpec(t *testing.T) {
expected: v1.PodSpec{ expected: v1.PodSpec{
NodeSelector: map[string]string{ NodeSelector: map[string]string{
"foo": "bar", "foo": "bar",
kubeadmconstants.LabelNodeRoleMaster: "", kubeadmconstants.LabelNodeRoleOldControlPlane: "",
}, },
}, },
}, },
@ -168,7 +168,7 @@ func TestSetControlPlaneTolerationOnPodSpec(t *testing.T) {
podSpec: &v1.PodSpec{}, podSpec: &v1.PodSpec{},
expected: v1.PodSpec{ expected: v1.PodSpec{
Tolerations: []v1.Toleration{ Tolerations: []v1.Toleration{
kubeadmconstants.ControlPlaneToleration, kubeadmconstants.OldControlPlaneToleration,
}, },
}, },
}, },
@ -182,7 +182,7 @@ func TestSetControlPlaneTolerationOnPodSpec(t *testing.T) {
expected: v1.PodSpec{ expected: v1.PodSpec{
Tolerations: []v1.Toleration{ Tolerations: []v1.Toleration{
{Key: "foo", Value: "bar"}, {Key: "foo", Value: "bar"},
kubeadmconstants.ControlPlaneToleration, kubeadmconstants.OldControlPlaneToleration,
}, },
}, },
}, },

View File

@ -208,21 +208,34 @@ func deleteHealthCheckJob(client clientset.Interface, ns, jobName string) error
// controlPlaneNodesReady checks whether all control-plane Nodes in the cluster are in the Running state // controlPlaneNodesReady checks whether all control-plane Nodes in the cluster are in the Running state
func controlPlaneNodesReady(client clientset.Interface, _ *kubeadmapi.ClusterConfiguration) error { func controlPlaneNodesReady(client clientset.Interface, _ *kubeadmapi.ClusterConfiguration) error {
selector := labels.SelectorFromSet(labels.Set(map[string]string{ // list nodes labeled with a "master" node-role
constants.LabelNodeRoleMaster: "", selectorOldControlPlane := labels.SelectorFromSet(labels.Set(map[string]string{
constants.LabelNodeRoleOldControlPlane: "",
})) }))
controlPlanes, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{ nodesWithOldLabel, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{
LabelSelector: selector.String(), LabelSelector: selectorOldControlPlane.String(),
}) })
if err != nil { if err != nil {
return errors.Wrap(err, "couldn't list control-planes in cluster") return errors.Wrapf(err, "could not list nodes labeled with %q", constants.LabelNodeRoleOldControlPlane)
} }
if len(controlPlanes.Items) == 0 { // list nodes labeled with a "control-plane" node-role
selectorControlPlane := labels.SelectorFromSet(labels.Set(map[string]string{
constants.LabelNodeRoleControlPlane: "",
}))
nodesControlPlane, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{
LabelSelector: selectorControlPlane.String(),
})
if err != nil {
return errors.Wrapf(err, "could not list nodes labeled with %q", constants.LabelNodeRoleControlPlane)
}
nodes := append(nodesWithOldLabel.Items, nodesControlPlane.Items...)
if len(nodes) == 0 {
return errors.New("failed to find any nodes with a control-plane role") return errors.New("failed to find any nodes with a control-plane role")
} }
notReadyControlPlanes := getNotReadyNodes(controlPlanes.Items) notReadyControlPlanes := getNotReadyNodes(nodes)
if len(notReadyControlPlanes) != 0 { if len(notReadyControlPlanes) != 0 {
return errors.Errorf("there are NotReady control-planes in the cluster: %v", notReadyControlPlanes) return errors.Errorf("there are NotReady control-planes in the cluster: %v", notReadyControlPlanes)
} }

View File

@ -22,9 +22,11 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
errorsutil "k8s.io/apimachinery/pkg/util/errors" errorsutil "k8s.io/apimachinery/pkg/util/errors"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/klog/v2" "k8s.io/klog/v2"
@ -251,3 +253,31 @@ func rollbackFiles(files map[string]string, originalErr error) error {
} }
return errors.Errorf("couldn't move these files: %v. Got errors: %v", files, errorsutil.NewAggregate(errs)) return errors.Errorf("couldn't move these files: %v. Got errors: %v", files, errorsutil.NewAggregate(errs))
} }
// LabelOldControlPlaneNodes finds all nodes with the legacy node-role label and also applies
// the "control-plane" node-role label to them.
// TODO: https://github.com/kubernetes/kubeadm/issues/2200
func LabelOldControlPlaneNodes(client clientset.Interface) error {
selectorOldControlPlane := labels.SelectorFromSet(labels.Set(map[string]string{
kubeadmconstants.LabelNodeRoleOldControlPlane: "",
}))
nodesWithOldLabel, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{
LabelSelector: selectorOldControlPlane.String(),
})
if err != nil {
return errors.Wrapf(err, "could not list nodes labeled with %q", kubeadmconstants.LabelNodeRoleOldControlPlane)
}
for _, n := range nodesWithOldLabel.Items {
if _, hasNewLabel := n.ObjectMeta.Labels[kubeadmconstants.LabelNodeRoleControlPlane]; hasNewLabel {
continue
}
err = apiclient.PatchNode(client, n.Name, func(n *v1.Node) {
n.ObjectMeta.Labels[kubeadmconstants.LabelNodeRoleControlPlane] = ""
})
if err != nil {
return err
}
}
return nil
}

View File

@ -303,7 +303,7 @@ func TestGetNodeRegistration(t *testing.T) {
}, },
}, },
Spec: v1.NodeSpec{ Spec: v1.NodeSpec{
Taints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, Taints: []v1.Taint{kubeadmconstants.OldControlPlaneTaint},
}, },
}, },
}, },
@ -583,7 +583,7 @@ func TestGetInitConfigurationFromCluster(t *testing.T) {
}, },
}, },
Spec: v1.NodeSpec{ Spec: v1.NodeSpec{
Taints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, Taints: []v1.Taint{kubeadmconstants.OldControlPlaneTaint},
}, },
}, },
}, },
@ -660,7 +660,7 @@ func TestGetInitConfigurationFromCluster(t *testing.T) {
}, },
}, },
Spec: v1.NodeSpec{ Spec: v1.NodeSpec{
Taints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, Taints: []v1.Taint{kubeadmconstants.OldControlPlaneTaint},
}, },
}, },
}, },

View File

@ -83,7 +83,7 @@ func SetBootstrapTokensDynamicDefaults(cfg *[]kubeadmapi.BootstrapToken) error {
} }
// SetNodeRegistrationDynamicDefaults checks and sets configuration values for the NodeRegistration object // SetNodeRegistrationDynamicDefaults checks and sets configuration values for the NodeRegistration object
func SetNodeRegistrationDynamicDefaults(cfg *kubeadmapi.NodeRegistrationOptions, ControlPlaneTaint bool) error { func SetNodeRegistrationDynamicDefaults(cfg *kubeadmapi.NodeRegistrationOptions, controlPlaneTaint bool) error {
var err error var err error
cfg.Name, err = kubeadmutil.GetHostname(cfg.Name) cfg.Name, err = kubeadmutil.GetHostname(cfg.Name)
if err != nil { if err != nil {
@ -91,8 +91,9 @@ func SetNodeRegistrationDynamicDefaults(cfg *kubeadmapi.NodeRegistrationOptions,
} }
// Only if the slice is nil, we should append the control-plane taint. This allows the user to specify an empty slice for no default control-plane taint // Only if the slice is nil, we should append the control-plane taint. This allows the user to specify an empty slice for no default control-plane taint
if ControlPlaneTaint && cfg.Taints == nil { if controlPlaneTaint && cfg.Taints == nil {
cfg.Taints = []v1.Taint{kubeadmconstants.ControlPlaneTaint} // TODO: https://github.com/kubernetes/kubeadm/issues/2200
cfg.Taints = []v1.Taint{kubeadmconstants.OldControlPlaneTaint}
} }
if cfg.CRISocket == "" { if cfg.CRISocket == "" {