-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ MS preflight checks to improve cluster stability #8595
✨ MS preflight checks to improve cluster stability #8595
Conversation
/retest |
ec31453
to
c58ad0b
Compare
// Check the Kubernetes version skew policy. | ||
// => MS minor version cannot be greater than the Control Plane minor version. | ||
// => MS minor version cannot be older than 2 minor version of Control Plane. | ||
// Kubernetes skew policy: https://kubernetes.io/releases/version-skew-policy/#kubelet | ||
floorVersion := semver.Version{ | ||
Major: cpSemver.Major, | ||
Minor: cpSemver.Minor - 2, | ||
Patch: 0, | ||
} | ||
if msSemver.GT(cpSemver) || msSemver.LT(floorVersion) { | ||
log.Info(fmt.Sprintf("Pre-flight check failed: MachineSet version (%s) and ControlPlane version (%s) do not conform to the kubernetes version skew policy", msVersion, cpVersion)) | ||
return ctrl.Result{RequeueAfter: preflightFailedRequeueAfter}, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be in a validation webhook?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which one? MD + MS?
At least for the latter check, the webhook is not enough as the CP version can just change and then existing MachineSets "fall" outside of the policy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be on both sides?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll have to think a bit about it, but sounds reasonable at a first glance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine to add both checks to the MD + MS validating webhook.
But they should only block on create and on update only if the version is changing. They shouldn't block an update where the version is not changed in my opinion
I would prefer implementing the webhooks in a follow-up PR though.
Hm, but it wouldn't make sense to disable the validation on the webhooks via the skip preflight check annotation. As the webhook is not a preflight check. We could maybe choose to only return warnings in the webhook? (or maybe rather add an unsafe annotation to skip the validation in the webhook)
@vincepri WDYT?
ms.Spec.Template.Spec.Bootstrap.ConfigRef.Kind == "KubeadmConfigTemplate" | ||
if kubeadmBootstrapProviderUsed { | ||
if cpVersion != msVersion { | ||
log.Info(fmt.Sprintf("Pre-flight check failed: MachineSet version (%s) and ControlPlane version (%s) do not conform to kubeadm version skew policy: kubeadm bootstrap provider only supports joining with the same version as the control plane", msVersion, cpVersion)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, shouldn't this allow users to create worker nodes with an older version that's still in the skew policy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The kubeadm skew policy is pretty strict:
If new nodes are joined to the cluster, the kubeadm binary used for kubeadm join must match the last version of kubeadm used to either create the cluster with kubeadm init or to upgrade the same node with kubeadm upgrade.
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#version-skew-policy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This skew policy is for the kubeadm binary, not for the kubelet version which joins the cluster (kubeadm even tests joining with an older kubelet binary).
So the preflight check would make the assumption, that the version set at the machineset matches kubeadm version used if I'm reading it correctly? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like @chrischdi, the above reads like it's mostly for the binary that sets the very minimal version based on the control plane init; which makes sense to me, although I should still be able to scale up/down or rollout Machine Deployments on an older version if the overall Kubernetes skew policy allows
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chrischdi The version set here determines the VM image (or the appropriate infra specific thing) used and the assumption is that VM image uses the matching kubeadm version binary (which I believe is the is the case for the providers).
@vincepri This preflight check is only performed if using the kubeadm bootstrap provider. The preflight check will only fail when trying to create new Machines (scale down still works) using the old version because kubeadm join
could fail as the kubeadm version skew is violated.
Along with that, the user can also just skip the kubeadm preflight check if the user has verified that new workers running an old version can join the control plane.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The preflight check will only fail when trying to create new Machines (scale down still works) using the old version because kubeadm join could fail as the kubeadm version skew is violated.
I'm not sure if I'm seeing the kubeadm skew issue here, given we should still allow to scale (up/down) pools of nodes on older versions, if the Kubernetes overall skew policy is respected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that joining new nodes with an older kubeadm version is not supported by kubeadm upstream. It mostly works but there is no test coverage for it.
An example can be seen here: #7533 (comment). The old kubeadm version wasn't able to parse the ClusterConfiguration written by the newer kubeadm version: (or in the Cluster API case, KCP)
error execution phase preflight: unable to fetch the kubeadm-config ConfigMap: failed to decode cluster configuration data: no kind "ClusterConfiguration" is registered for version "kubeadm.k8s.io/v1beta3" in scheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme/scheme.go:31"
But this is just an example we're aware of, as there is no testing on the kubeadm side there simply is no official support for this.
Our idea was to have a preflight check to ensure we're acting within the official support ranges of kubeadm & Kubernetes. For folks who are sure that other combinations work as well (I assume because they tested it) we wanted to provide a way to opt-out.
There are a few cases where it's better to not act if we're outside of the support range and thus can't tell if the Machine has a chance to come up:
- MHC: It's better to keep an (at least momentarily) unhealty Machine vs deleting it and then the creation/join fails
- If autoscaler scales up a MD/MS with an older version and the Machine creations/joins continously fail we can have a lot of Machines around which have no chance for success but can become pretty expensive
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First round of feedback, I'll take a closer look tomorrow
ms.Spec.Template.Spec.Bootstrap.ConfigRef.Kind == "KubeadmConfigTemplate" | ||
if kubeadmBootstrapProviderUsed { | ||
if cpVersion != msVersion { | ||
log.Info(fmt.Sprintf("Pre-flight check failed: MachineSet version (%s) and ControlPlane version (%s) do not conform to kubeadm version skew policy: kubeadm bootstrap provider only supports joining with the same version as the control plane", msVersion, cpVersion)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The kubeadm skew policy is pretty strict:
If new nodes are joined to the cluster, the kubeadm binary used for kubeadm join must match the last version of kubeadm used to either create the cluster with kubeadm init or to upgrade the same node with kubeadm upgrade.
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#version-skew-policy
// Check the Kubernetes version skew policy. | ||
// => MS minor version cannot be greater than the Control Plane minor version. | ||
// => MS minor version cannot be older than 2 minor version of Control Plane. | ||
// Kubernetes skew policy: https://kubernetes.io/releases/version-skew-policy/#kubelet | ||
floorVersion := semver.Version{ | ||
Major: cpSemver.Major, | ||
Minor: cpSemver.Minor - 2, | ||
Patch: 0, | ||
} | ||
if msSemver.GT(cpSemver) || msSemver.LT(floorVersion) { | ||
log.Info(fmt.Sprintf("Pre-flight check failed: MachineSet version (%s) and ControlPlane version (%s) do not conform to the kubernetes version skew policy", msVersion, cpVersion)) | ||
return ctrl.Result{RequeueAfter: preflightFailedRequeueAfter}, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which one? MD + MS?
At least for the latter check, the webhook is not enough as the CP version can just change and then existing MachineSets "fall" outside of the policy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First round of feedback, I'll take a closer look tomorrow
/area machineset |
// Check the Kubernetes version skew policy. | ||
// => MS minor version cannot be greater than the Control Plane minor version. | ||
// => MS minor version cannot be older than 2 minor version of Control Plane. | ||
// Kubernetes skew policy: https://kubernetes.io/releases/version-skew-policy/#kubelet | ||
floorVersion := semver.Version{ | ||
Major: cpSemver.Major, | ||
Minor: cpSemver.Minor - 2, | ||
Patch: 0, | ||
} | ||
if msSemver.GT(cpSemver) || msSemver.LT(floorVersion) { | ||
log.Info(fmt.Sprintf("Pre-flight check failed: MachineSet version (%s) and ControlPlane version (%s) do not conform to the kubernetes version skew policy", msVersion, cpVersion)) | ||
return ctrl.Result{RequeueAfter: preflightFailedRequeueAfter}, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine to add both checks to the MD + MS validating webhook.
But they should only block on create and on update only if the version is changing. They shouldn't block an update where the version is not changed in my opinion
I would prefer implementing the webhooks in a follow-up PR though.
Hm, but it wouldn't make sense to disable the validation on the webhooks via the skip preflight check annotation. As the webhook is not a preflight check. We could maybe choose to only return warnings in the webhook? (or maybe rather add an unsafe annotation to skip the validation in the webhook)
@vincepri WDYT?
c21ccfb
to
e63fa65
Compare
LGTM label has been added. Git tree hash: e3d9cbd57e8207a0a1ddecbee534b716b1cb300b
|
Based on the discussion during the May 17th office hours we decided to place the MachineSet preflight checks behind a feature gate ( The feature gate is alpha will be off by default and therefore there wont be any changes to any of the existing behavior. This will give us time in the mean time as kubeadm works on its version skew. |
0241aa6
to
c128409
Compare
@ykakarap: The following tests failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
/retest |
/lgtm |
LGTM label has been added. Git tree hash: 4b4ef83d318a6ebde5c80d7d497d7f808e59a744
|
/lgtm approve pending squash |
LGTM label has been added. Git tree hash: 06fb9ba8d474f56d9564a9b440bd7963552c4817
|
/lgtm |
fdfd263
to
5b6a0f7
Compare
Squashed. |
/lgtm Thank you very much! |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: sbueringer The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
What this PR does / why we need it:
This PR adds pre-flight checks before a new Machine is created in the MachineSet controller. These pre-flight checks will help with improving the stability of the cluster.
The following pre-flight checks are performed:
Which issue(s) this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)
format, will close the issue(s) when PR gets merged):Fixes #8657