Skip to content

Commit

Permalink
Apply uninitialized taint to nodes at creation
Browse files Browse the repository at this point in the history
and delete after labels are synced
  • Loading branch information
Yuvaraj Kakaraparthi committed Jan 26, 2023
1 parent 67faaee commit 13927b3
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 3 deletions.
5 changes: 5 additions & 0 deletions api/v1beta1/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ const (
ReplicasManagedByAnnotation = "cluster.x-k8s.io/replicas-managed-by"
)

var NodeUninitializedTaint = corev1.Taint{
Key: "node.cluster.x-k8s.io/uninitialized",
Effect: corev1.TaintEffectNoSchedule,
}

const (
// TemplateSuffix is the object kind suffix used by template types.
TemplateSuffix = "Template"
Expand Down
51 changes: 48 additions & 3 deletions bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ const (
KubeadmConfigControllerName = "kubeadmconfig-controller"
)

const (
controlPlaneTaint = "node-role.kubernetes.io/control-plane"
)

const (
// DefaultTokenTTL is the default TTL used for tokens.
DefaultTokenTTL = 15 * time.Minute
Expand Down Expand Up @@ -415,7 +419,14 @@ func (r *KubeadmConfigReconciler) handleClusterNotInitialized(ctx context.Contex
},
}
}
initdata, err := kubeadmtypes.MarshalInitConfigurationForVersion(scope.Config.Spec.InitConfiguration, parsedVersion)

// Add the node uninitialized taint to the list of taints.
// Nb. For control planes if InitConfiguration.NodeRegistration.Taints is nil the control-plane taint is applied by
// default. Make sure to add the taint.
initConfiguration := scope.Config.Spec.InitConfiguration.DeepCopy()
addNodeUninitializedTaint(&initConfiguration.NodeRegistration, true)

initdata, err := kubeadmtypes.MarshalInitConfigurationForVersion(initConfiguration, parsedVersion)
if err != nil {
scope.Error(err, "Failed to marshal init configuration")
return ctrl.Result{}, err
Expand Down Expand Up @@ -545,13 +556,17 @@ func (r *KubeadmConfigReconciler) joinWorker(ctx context.Context, scope *Scope)
return res, nil
}

// Add the node uninitialized taint to the list of taints.
joinConfiguration := scope.Config.Spec.JoinConfiguration.DeepCopy()
addNodeUninitializedTaint(&joinConfiguration.NodeRegistration, false)

kubernetesVersion := scope.ConfigOwner.KubernetesVersion()
parsedVersion, err := semver.ParseTolerant(kubernetesVersion)
if err != nil {
return ctrl.Result{}, errors.Wrapf(err, "failed to parse kubernetes version %q", kubernetesVersion)
}

joinData, err := kubeadmtypes.MarshalJoinConfigurationForVersion(scope.Config.Spec.JoinConfiguration, parsedVersion)
joinData, err := kubeadmtypes.MarshalJoinConfigurationForVersion(joinConfiguration, parsedVersion)
if err != nil {
scope.Error(err, "Failed to marshal join configuration")
return ctrl.Result{}, err
Expand Down Expand Up @@ -651,13 +666,19 @@ func (r *KubeadmConfigReconciler) joinControlplane(ctx context.Context, scope *S
return res, nil
}

// Add the node uninitialized taint to the list of taints.
// Nb. For control planes if JoinConfiguration.NodeRegistration.Taints is nil the control-plane taint is applied by
// default. Make sure to add the taint.
joinConfiguration := scope.Config.Spec.JoinConfiguration.DeepCopy()
addNodeUninitializedTaint(&joinConfiguration.NodeRegistration, true)

kubernetesVersion := scope.ConfigOwner.KubernetesVersion()
parsedVersion, err := semver.ParseTolerant(kubernetesVersion)
if err != nil {
return ctrl.Result{}, errors.Wrapf(err, "failed to parse kubernetes version %q", kubernetesVersion)
}

joinData, err := kubeadmtypes.MarshalJoinConfigurationForVersion(scope.Config.Spec.JoinConfiguration, parsedVersion)
joinData, err := kubeadmtypes.MarshalJoinConfigurationForVersion(joinConfiguration, parsedVersion)
if err != nil {
scope.Error(err, "Failed to marshal join configuration")
return ctrl.Result{}, err
Expand Down Expand Up @@ -1066,3 +1087,27 @@ func (r *KubeadmConfigReconciler) ensureBootstrapSecretOwnersRef(ctx context.Con
}
return nil
}

func addNodeUninitializedTaint(nodeRegistration *bootstrapv1.NodeRegistrationOptions, isControlPlane bool) {
taints := nodeRegistration.Taints
if isControlPlane && taints == nil {
// NOTE: Might need to add the old taint, new taint or both depending on the kubernetes version.
taints = []corev1.Taint{{
Key: controlPlaneTaint,
Effect: corev1.TaintEffectNoSchedule,
}}
}
if !hasUninitializedTaint(taints) {
taints = append(taints, clusterv1.NodeUninitializedTaint)
}
nodeRegistration.Taints = taints
}

func hasUninitializedTaint(taints []corev1.Taint) bool {
for _, taint := range taints {
if taint.MatchTaint(&clusterv1.NodeUninitializedTaint) {
return true
}
}
return false
}
23 changes: 23 additions & 0 deletions internal/controllers/machine/machine_controller_noderef.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,29 @@ func (r *Reconciler) reconcileNode(ctx context.Context, cluster *clusterv1.Clust
}
}

// Reconcile node taints
// TODO: should I get the node again before I can drop the taint from the node?
taints := []corev1.Taint{}
patchHelper, err = patch.NewHelper(node, remoteClient)
if err != nil {
return ctrl.Result{}, errors.Wrap(err, "failed to create patch helper")
}
nodeHasUninitializedTaint := false
for _, taint := range node.Spec.Taints {
if taint.MatchTaint(&clusterv1.NodeUninitializedTaint) {
nodeHasUninitializedTaint = true
continue
}
taints = append(taints, taint)
}
if nodeHasUninitializedTaint {
node.Spec.Taints = taints
if err := patchHelper.Patch(ctx, node); err != nil {
log.V(2).Info("Failed patch node to set taints", "err", err, "node name", node.Name)
return ctrl.Result{}, err
}
}

// Do the remaining node health checks, then set the node health to true if all checks pass.
status, message := summarizeNodeConditions(node)
if status == corev1.ConditionFalse {
Expand Down

0 comments on commit 13927b3

Please sign in to comment.