-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Adding JSON configuration options for overwrites to bootstrap script #875
Conversation
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.
@cartermckinnon anything you want to add to this?
files/bootstrap.sh
Outdated
@@ -55,6 +56,11 @@ while [[ $# -gt 0 ]]; do | |||
shift | |||
shift | |||
;; | |||
--kubelet-extra-json-config) |
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.
- You've defined the arg as
--kubelet-extra-json-args
in the helper on #L23. Can we instead have this as--kubelet-extra-json-config-file
and take a pointer to a file instead of the file contents? - You probably also want to default
KUBELET_EXTRA_JSON_CONFIG
like on #L126, otherwise it might fail with this variable not being bound in theif -n
check later on.
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, I'm not sure we can. I remember something about this, but we pass it in as definitive data. I don't think we can make it be on the instance when this is being executed.
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.
Yep. This is incoming data. We can't make it point to a file which we can't make to exist.
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.
Do you mean incoming as in supplied by the eksctl user? Also, why can't we make the file exist? You're calling the bootstrap script yourself in UserData so why not create the file and seed the contents in 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.
My only nit is I'd call this --kubelet-extra-config
/KUBELET_EXTRA_CONFIG
. We don't need to mention the format of the config file here, and this should have the same semantics as --kubelet-extra-args
.
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.
Create the file with what content? :) To be more precise, yes this is data coming from an outside user. For example eksctl
. They don't have access to the node or aren't running a custom AMI so all the entry they have is user data. eksctl is no longer constructing userdata. I know we could add things as a file, but for that to happen, we would have to again, mess with user data. This is just plain incoming Json extension of the kube config.
I guess I can overload this setting to also accept a file and then we assume the file exists somehow ( either by putting it there by hand in a custom AMI or making the UserData create the file ) and load the contents. It just feels like overloading a single flag to have multiple purpose is a bad idea. :D But that's just my IMHO. :)
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.
eksctl is no longer constructing userdata
Maybe I'm misunderstanding, but isn't eksctl creating userData with /etc/eks/bootstrap.sh $args
? I don't think I quite understand why eksctl cannot take in the json input for kubeletExtraConfig
, put it in a file and then provide it to the bootstrap script.
If instead, it an eksctl customer that's fully authoring their UserData (including their bootstrap script), then I'd expect them to do -
cat <<EOF > /etc/eks/kubelet-custom-config.json
{
"kubeReserved": 240m
}
EOF
/etc/eks/bootstrap.sh --kubelet-extra-config /etc/eks/kubelet-custom-config.json $otherArgs
I understand that the eksctl API accepts additional kubelet config as JSON / YAML input if I'm reading this right, but I don't think we need to force the bootstrap script's interface to also match that semantic.
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.
It doesn't work, because anything we do just gets overwritten ultimately in this script. Whatever we do outside, the value just gets clobbered over with some defaults.
The reason we don't do the first part is that using kubelet-extra-config
is cumbersome and overly complex for simple values and passing in some json data. :)
if [[ -n "${KUBELET_EXTRA_JSON_CONFIG}" ]]; then | ||
TMP_KUBE_CONF='/tmp/kubelet-conf-temp.json' | ||
KUBELET_CONFIG_EXTRA='/tmp/kubelet-conf-extra.json' | ||
echo '%s' > ${KUBELET_CONFIG_EXTRA} |
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 we take in a pointer to a file, could we change this entire section to something simpler like -
if [[ -n "${KUBELET_EXTRA_JSON_CONFIG}" ]]; then
echo "bootstrap.sh: merging user json options into kubelet-config.json"
jq -s '.[0] + .[1]' "${KUBELET_CONFIG}" "${KUBELET_EXTRA_JSON_CONFIG}" > $KUBELET_CONFIG
fi
jq
doesn't produce a partial result, so we shouldn't need to redirect to a temp file and then copy it over unless I'm missing something else :)
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.
Yeah if I remember correctly, this indirection was added because of a different thing. But it was a couple months ago now, so I'll try to remember why.
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 is incoming data that gets merged with the existing data.
files/bootstrap.sh
Outdated
@@ -20,6 +20,7 @@ function print_help { | |||
echo "--b64-cluster-ca The base64 encoded cluster CA content. Only valid when used with --apiserver-endpoint. Bypasses calling \"aws eks describe-cluster\"" | |||
echo "--apiserver-endpoint The EKS cluster API Server endpoint. Only valid when used with --b64-cluster-ca. Bypasses calling \"aws eks describe-cluster\"" | |||
echo "--kubelet-extra-args Extra arguments to add to the kubelet. Useful for adding labels or taints." | |||
echo "--kubelet-extra-json-args Extra json configuration for kubelet. Userful for adding all kinds of extra configuration such as evictionHard or kubeReserved settings in JSON format." |
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.
Can we also add Will override any conflicting setting that the script defaults to.
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'd like to see this support extra config in a file, as @suket22 brought up. I'm not opposed to supporting JSON inline in addition to this.
We could call the option --kubelet-extra-config
/KUBELET_EXTRA_CONFIG
, and if the value isn't a valid file, treat it as inline JSON.
But that's a separate issue. This issue deals with the fact when there is extra input from the user to a node on which there are no extra files. Only incoming data that we would like to merge with kube config. I can add an extra flag that deals with that. I think making this value to be both needlessly complicates things including the parsing and detecting if it's a file or not. Not to mention overloading the naming and the purpose of a single flag. SRP and all that? |
Overloading a single arg to either be a file or actual content seems odd to me, and don't think we should go down the route. |
I suggested it, because:
It's not a hill I need to die on, but it sounds like inline JSON was @Skarlso 's original goal here. |
I'd like to get some more context on how |
@cartermckinnon Ah I might have misunderstood what you want. You would like to change an existing flag to either accept a file or a set of JSON data? That wouldn't be a problem actually. How we would leverage it actually is by just providing a few things without them getting overwritten with a nice value which doesn't require us to pass in a convoluted thing where we have to pre-create files and edit everything. We have existing code which translates and creates data based on custom YAML data which is then just directly forwarded to the bootstrap script. apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: dev-cluster-1
region: eu-north-1
nodeGroups:
- name: ng-1
instanceType: m5a.xlarge
desiredCapacity: 1
kubeletExtraConfig:
kubeReserved:
cpu: "300m"
memory: "300Mi"
ephemeral-storage: "1Gi"
kubeReservedCgroup: "/kube-reserved"
systemReserved:
cpu: "300m"
memory: "300Mi"
ephemeral-storage: "1Gi"
evictionHard:
memory.available: "200Mi"
nodefs.available: "10%"
featureGates:
RotateKubeletServerCertificate: true # has to be enabled, otherwise it will be disabled This is super easy and convenient for the users. We don't write this out into a file and try to merge them together with other data. We pass in our thing, and would pass this in which than uses the bash magic to create the extra kube config that then can be used to set things up. It's really slick and nice user flow IMHO. Now, if I could pass this very same thing into kube-extra-config I'm okay with that too as long as everything gets applied properly. :) Oh and it needs to happen after bootstrap is finished so things will be applied correctly. |
I know how to implement it, that wasn't my problem with it. :D if [[ -n "${KUBELET_EXTRA_CONFIG}" ]]; then So you're thinking about a scenario where there is a custom AMI and the file has been already backed into it, I guess? ( Or UserData defined more than one file ). I can see that being a thing, however, I just would like to point out that just because others do something it doesn't make it a good thing. :D But I can get behind that I guess. |
I was actually thinking of using this in the context of MIME multi-parts, where the first part (maybe user managed) populates the file and the second part uses this file. This could help folks override kubelet settings on Managed Nodes and Karpenter, without going the full custom AMI route. We'd establish a runtime contract stating "always put your kubeletConfig in this path |
If the data can be passed in, sure. I don't see the point though since you can merge the data immediately. But maybe I'm missing something there. :) The main point is, that incoming data trying to do anything will be overwritten with data defaulted in the bootstrap script. That's what we are trying to avoid / fix here. |
@suket22 doesn't #855 cover most of the use case here (I know it's not perfect)? Basically additional kubelet args can be set but you can't override values explicitly set in bootstrap.sh. I'd think that the desired logic, however it is implemented, should be that values which bootstrap.sh sets explicitly need inputs to override if it's valid to do so and anything else should able to be appended. In addition to work with MNGs there needs to be a way to persist the user input after it's passed in as multi part data. |
@stevehipwell as written in eksctl-io/eksctl#4459 (comment) we would like to avoid setting a gazillion specific arguments that are a maintenance nightmare and can change over time. Where as, passing in a stream of JSON data can be arbitrary in any regard and up to the user to define entirely. |
@Skarlso the only specific arguments or env values are to override bootstrap.sh explicitly set kubelet args, which need to integrate with the bootstrap logic. In your desired design the full context of the bootstrapping is lost from your modifications, so there will be more settings off limits especially for MNGs. |
Sorry, is this an incomplete sentence? :D
I can't really parse what you mean here.
What? :D Which context are you referring to? |
@Skarlso I don't think it's incomplete; if you're using bootstrap.sh you will need to provide variables to customise it's behaviour around the configuration it explicitly sets. For everything else you should be able to pass through your configuration, but you do need to know what can't be passed through. The context comes from the fact that kubelet args may, and often do, have corresponding changes required and from the fact that in the context of a MNG there are more constraints. If done right bootstrapping should follow an open/closed design; you provide constrained input variables to configure the closed functionality and then extend on top of the result within the constraints allowed, which can be dynamically set based on the bootstrap inputs. E.g. disable default kube reserved values being calculated with a bootstrap variable and pass kube reserved values through (only allowed because of the bootstrap input). |
ah, thanks for the longer explanation, that makes more sense now. Yes, the values are dependent, sure. And some things need to be calculated based on those values. But where is that requirement coming from? What I mean is, can it be left to the user saying, listen, of you set X you need to be sure you set Y properly for things to work otherwise, they might break and we don't take responsibility on that. If you know what I'm saying? Otherwise, I agree that we should let things lying around with which the user can shoot themselves in the foot I guess. In which case, the argument based approach would make more sense because it gives more control on other calculations? |
@stevehipwell For sure, but that's a massive step up from this small little option to define custom Kube config, right? |
Hmmm. I'm not completely against doing it, if it would be beneficial :) |
I'm convinced a new bootstrap binary is needed and probably isn't too hard to implement. We need better input options into a bootstrap script and we need better testing. The bash script has gotten us pretty far, but a bootstrap script that uses the same or similar format to Bottlerocket would be optimal IMO. The configuration scope in a new bootstrap binary could probably be scoped down quite a bit at first. We could start by supporting mostly what the current bootstrap script supports but fix the mechanisms for passing input and the order of overrides / merges. We could also get rid of some older support that bootstrap script has, like the There are other advantages to a new bootstrap script, for example, unifying the AL2, eventual AL2022, and Windows bootstrap processes into one project. |
Heck, let's do it. I'm game. Do you have a ticket? Should I close this? What do you prefer? |
@bwagner5 with a limited initial config scope and init container support all use cases would be catered for. As more of the Bottlerocket config is supported the fewer use cases would need init containers. I'd suggest that this binary is created in a new repo and that a future aim is to make the logic available as a package to be imported where required (e.g. Karpenter to replicate reserved logic). I'd be keen to contribute to this effort. |
So..... what happens to this now? :D |
I'm going to close this, because the consensus is that a re-write of the bootstrap is the right time/way to make this change. My hope is that can land in/around AL2023 support. |
@stevehipwell @cartermckinnon do you know if something has being started in this context ? I would like to help but I don't know if something has changed in the last months |
for kubelet specifically, I would recommend waiting for 1.28 and utilizing the new drop-in configuration directory https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/#kubelet-conf-d This would allow the EKS AMI to set the required values and allow users to augment by writing the values they wish to set into a config file in that drop in directory. This should also play quite nicely with managed nodegroups where the EKS service is actually calling the bootstrap command which makes it difficult for users to pass additional flags The one change we might need to make here is to add support for the |
Closes #873
Description of changes:
Changes
bootstrap.sh
to accept a JSON kubelet config which merges it with the existing config after all changes have been applied by the bootstrap script.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.