-
Notifications
You must be signed in to change notification settings - Fork 524
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
[Draft] Add new setting: eviction-hard #1341
Conversation
* `settings.kubernetes.eviction-hard`: The hard eviction Signal and Thresholds you set up to reclaim the associated starved resource. | ||
Remember to quote keys (since they often contain ".") and to quote all values. | ||
* Example user data for setting up eviction hard: | ||
``` |
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 fix this indent.
"nodefs.inodesFree" = "15Mi" | ||
"pid.available" = "15%" | ||
``` | ||
|
||
|
||
You can also optionally specify static pods for your node with the following settings. |
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.
Question: There are four settings, and wonder if it's better to make four PRs for them (one PR for each setting.) Ben mentioned that we should make them in different commits and same PR. I think maybe it's better to have four PR, because all of them have different testing and implementation requirement. Can I get some suggestions on that? thanks!
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.
If the commits have no inter-dependencies and can stand alone by themselves I don't think we have to have them in the same PR. That being said, if you already have them ready, and they're similar in scope to this commit you have out right now, it'd be nice to have them all in the PR and reviewers can just review commit by commit instead of having to jump through 4 PRs that might end up with similar review comments.
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.
+1 to that
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.
Nice ! 🎉
EvictionHardValue::try_from(*err).unwrap_err(); | ||
} | ||
} | ||
} |
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.
nit: new line
@@ -62,6 +62,8 @@ pub mod error { | |||
field: String, | |||
source: serde_plain::Error, | |||
}, | |||
#[snafu(display("Invalid eviction hard '{}': {}", input, msg))] | |||
InvalideEvictionHard { input: String, msg: String }, |
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.
we can create two different error enums, one for Key and other for value. So, that you don't have to specifically pass a msg string and we can include msg string as part of #[snafu(display
to create string you want.
Did you refer it from somewhere, where we are using same enum ? I checked ECSAttributeKey
and ECSAttributeValue
we are using different error enum there.
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.
Your suggestion could be a way as well. The reason why I make them as one is trying to make simple and clear. and I agree with you that different error enums could be a better way. Btw, I got this idea from KubernetesLableKey
and KubernetesLabelValue
.
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 reason why we have error variants like this is because there might be a lot of special cases we check for and capturing each one as a separate error variant would be too much when all we want to convey is the value is invalid for so-and-so reason. An example of this is InvalidSysctlKey
.
If we only return this error in one location I would use #[snafu(display)]
. If there's more than one check that check for different things that might return this, then I think having it like this is fine.
type Error = error::Error; | ||
|
||
fn try_from(input: &str) -> Result<Self, Self::Error> { | ||
let evitionsignal = vec![ |
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.
we can also use enum here for example: https://github.com/bottlerocket-os/bottlerocket/blob/develop/sources/models/src/modeled_types/ecs.rs#L189
However, I don't know which aligns more to our existing style, I would let other comment on what we should use.
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 was trying to use enum to handle this part; however, I think enum could be not that efficient and clear there because too many works on dealing with variables which contains dots like memory.available
. I got some ideas that if we can use rename attributes for each enum variant #[serde(rename = "memory.available")]
, and I'm not sure if that worths. Appreciate for the comments! :)
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.
Another plus to just having it as an enum is being able to reuse it elsewhere (e.g. in your tests) for matching/validation etc.
I also wonder if we even need any of the traits here for converting to/from strings if EvictionHardKey
itself was the enum. We've never tried that before but I don't see a clear reason why we can't just rely on serde's deserialization trait (with the appropriate attributes like you mentioned) for validation.
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.
@gthao313 I think the rename attributes you mentioned above should allow us to use an enum. If so, that's probably the preferred route as other folks mentioned.
@@ -29,6 +29,8 @@ authorization: | |||
clusterDomain: {{settings.kubernetes.cluster-domain}} | |||
clusterDNS: | |||
- {{settings.kubernetes.cluster-dns-ip}} | |||
evictionHard: |
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.
what would happen if user does not set this setting ? I guess this setting would still exist in kubelet config without any value. Should we wrap setting in if ? for example:
{{~#if settings.kubernetes.evictionHard }}
evictionHard:
{{join_map ": " "\n " "no-fail-if-missing" settings.kubernetes.eviction-hard}}
{{~/if}}
I would let others weigh in, I am also learning in this commit :)
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.
Correct. The eviction-hard
setting would still there and would not effect kubelet start
. Your example is a good suggestion to me. Thanks 👍
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.
Yes - I think we should wrap this in an if
.
"nodefs.inodesFree" = "15Mi" | ||
"pid.available" = "15%" | ||
``` | ||
|
||
|
||
You can also optionally specify static pods for your node with the following settings. |
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.
+1 to that
@@ -29,6 +29,8 @@ authorization: | |||
clusterDomain: {{settings.kubernetes.cluster-domain}} | |||
clusterDNS: | |||
- {{settings.kubernetes.cluster-dns-ip}} | |||
evictionHard: |
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.
Yes - I think we should wrap this in an if
.
// =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= | ||
|
||
/// EvictionHardKey represents a string that contains a valid Kubernetes eviction hard | ||
/// signal. There are few valid eviction hard signals [memory.available], [nodefs.available], |
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.
nit: Rather than naming the currently available values, let's just point to the relevant k8s page so if more are added or if they change, we don't need to remember to update this comment.
Available eviction hard signals: <link here>
type Error = error::Error; | ||
|
||
fn try_from(input: &str) -> Result<Self, Self::Error> { | ||
let evitionsignal = vec![ |
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.
@gthao313 I think the rename attributes you mentioned above should allow us to use an enum. If so, that's probably the preferred route as other folks mentioned.
// =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= | ||
|
||
/// EvictionHardValue represents a string that contains a valid Kubernetes eviction threshold quantity | ||
/// An eviction threshold can be expressed as Gi/Mi or a percentage using the % token |
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.
Same down here - let's just point to the docs rather than reiterating them.
fn try_from(input: &str) -> Result<Self, Self::Error> { | ||
|
||
ensure!( | ||
input.ends_with("Gi") || input.ends_with("Mi") || input.ends_with("%"), |
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.
Let's make sure that these are the only values that are possible (Gi
, Mi
, %
) I took a peek at the doc page, but perhaps I missed the listing of acceptable values.
@@ -62,6 +62,8 @@ pub mod error { | |||
field: String, | |||
source: serde_plain::Error, | |||
}, | |||
#[snafu(display("Invalid eviction hard '{}': {}", input, msg))] | |||
InvalideEvictionHard { input: String, msg: String }, |
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.
s/InvalideEvictionHard/InvalidEvictionHard
(There's an extra "e" after Invalid)
input.ends_with("Gi") || input.ends_with("Mi") || input.ends_with("%"), | ||
error::InvalideEvictionHard { | ||
input, | ||
msg: format!("must be ends with Gi, Mi, or %"), |
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.
"must end with ..."
Get some feedbacks from this draft, which can help me in implementing another three settings
Issue number:
#1140
Description of changes:
Add new setting
eviction-hard
to k8s. User can specify this setting in userdata.[settings.kubernetes.eviction-hard]
"memory.available" = "10Gi"
"nodefs.inodesFree" = “15%”
Testing done:
Build aws-eks-* images and launched instance.
Test step1:
Go to control container run
apiclient -u /settings
to check if expected setting is there.eviction-hard":{"memory.available":"99.999%"}
Test step2:
ssh to admin contianer and look
etc/kubernetes/kubelet/config
to check if expected config is there.Test step3 - test effected/behavior:
set up eviction threshold to a high value for triggering eviction.
a) Go to EKS to check node condition
b) In admin contianer, check kubelet log by
journalctl -u kubelet
Terms of contribution:
By submitting this pull request, I agree that this contribution is dual-licensed under the terms of both the Apache License, version 2.0, and the MIT license.