-
Notifications
You must be signed in to change notification settings - Fork 38.6k
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
Set enableServiceLinks to false as default #121787
Comments
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the The 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. |
/sig network |
I think a changed default will be rejected for backward compatibility reasons, but have you considered a mutating webhook? |
So, I have seen a solution to use Kyverno. Example: With this proposal, I am trying to accomplish this:
FWIW, I believe this is the code that performs this action. |
Here is an example of an error we ran into where too many environment variables were set in Java, causing the container to crash. Setting |
I don't question the problem, and I agree that the environment variables are basically obsolete, and the default should be enableServiceLinks=false, but... With a so large customer base as K8s has, changing defaults is very risky. According to Hyrum's law it will ruin someones workflow. Then again, this change may be acceptable. I will bring it up if I attend the next sig/network bi-weekly meeting. |
It should be noted that even with |
This one is hard. Changing defaults is a breaking change. The real answer is to rev the "core" API to v2 at which point which we can change defaults. But that's a big topic. BIG. We can easily do a dumb admission controller (always set it to false), but I'll have to look into whether we can be smarter and only set it if the user didn't speciically ask for Earliest that could happen would be 1.30. Using gatekeeper or kyverno is something that can work NOW. @jpbetz @deads2k @apelisse - do you think that we should solve for this general problem? Specifically, should we have a normal way to set default values AFTER admission control? Or that admission control could categorically know "this value was set by the user" vs "this was set by defaulting" ? Is there some way? |
Technically, one could look at the managed fields to see if the field was applied (since we don't track defaulted fields), that can probably be done in the admission chain. I can't remember if we send the full managed fields to the admission webhooks, but I think we do. |
I would like to explain why I don't think this is a one-man problem, or a corner-case that can be taken lightly. A very large environment is a burden for fork/exec intensive applicationsThe environment is copied to child processes. A smart OS like Linux may have some copy-on-demand policy for environments, but even so many programs alter their environment, interpreters in particular. Just check the Depending on start order the problem may not be seen at firstIn Unix'es the environment of a running process is only altered by the process itself. So, PODs that are started before the services are created will have small environments. They can run without problems a long time, but when the POD is restarted it will suddenly get the very large environment that it can't handle, and dive into a restart-loop in worst case. Experiments and testsI wrote a script that creates a number of services:
createsvcs#! /bin/sh
##
## namespace=default prefix=test-service selector="app: alpine-env" \
## createsvcs <number>
##
## Create a number of Kubernetes services for test.
##
if test -z "$1"; then
grep '^##' $0 | cut -c3-
exit 0
fi
test -n "$namespace" || namespace=default
test -n "$prefix" || prefix=test-service
test -n "$selector" || selector="app: alpine-env"
# createsvc <name> <selector>
createsvc() {
# cat | kubectl create -f - <<EOF
# Some shells (bash) appends the caller's stdin to the command above
# for some reason, so the command hangs
local tmp=/tmp/$1.yaml
cat > $tmp <<EOF
apiVersion: v1
kind: Service
metadata:
name: $1
spec:
selector:
$2
ports:
- port: 7005
EOF
kubectl create -n $namespace -f $tmp
rm -f $tmp
}
cnt=$1
while test $cnt -gt 0; do
createsvc $(printf "$prefix-%04d" $cnt) "$selector"
cnt=$((cnt - 1))
done Start a POD and check it's environment:
The issue author got a Java crash for an environment >5100 lines. My test POD doesn't crash, so that specific problem may be for Java. alpine-env.yamlapiVersion: apps/v1
kind: Deployment
metadata:
name: alpine-env
spec:
selector:
matchLabels:
app: alpine-env
replicas: 1
template:
metadata:
labels:
app: alpine-env
spec:
#enableServiceLinks: false
containers:
- name: alpine
image: alpine:latest
imagePullPolicy: IfNotPresent
command: ["nc", "-lk", "-p", "7005", "-e", "hostname"]
ports:
- name: nc
containerPort: 7005 Set
As you can see the "kubernetes" service is defined even with |
I'm not saying I disagree. This is bad. What I am saying is that changing it would be a breaking change, and we just don't do that. If we think this is important enough to violate our own rules, why? If we think it is unlikely to break anyone, where's the data to back that? Doing an optional admission controller is the only non-breaking way to do this. If someone wants to do it, it should not be technically hard. |
Just if someone wonders how difficult is to create an admission controller check #97395 , is a good opportunity for contributors that have certain experience with the kubernetes code base /help |
@aojea: GuidelinesPlease ensure that the issue body includes answers to the following questions:
For more details on the requirements of such an issue, please see here and ensure that they are met. If this request no longer meets these requirements, the label can be removed In response to this:
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. |
Thanks, everyone, for reviewing this and offering solutions. I want to work on this issue and have development experience with admissions webhooks that may help 🤞 . However, I am a first-time contributor so it will take me much longer. |
No pressure! It's been this way for almost 10 years :) |
/assign @jmcgrath207 |
Since I haven't written a webhook myself, I took the opportunity to learn. Available at: https://github.com/uablrek/slink-webhook |
@apelisse I was playing with the PR in #122631 and dumping the object that arrives at the admission plugin I can not see any difference in the ManagedFields values between setting it on creation or defaulting Explicitly setting it
Defaulting:
|
@jpbetz @liggitt do you know , maybe, if is it possible to use managedfields for differentiating between defaulting by the apiserver or explicitly set by the user? |
That's surprising to me, but I verified that normal
(the issues with managedFields including defaulted fields aside) I think you can do something like the following on pod create:
|
First point, you can (and do) make breaking changes, you just need to announce the plan to make the deprecation, waiting period, then implementation. So, as an example, k8s-v21 will deprecate the old missing default value of "true" with an emitted warning and in k8s-v24 it will be changed from true to false. The deprecations page will show you that the value is changing. Documentation can point you to an upgrade path or alternatives. Second point, nobody in their right minds would use this feature as implemented: I am not aware of any use cases in my experience of applications looking for (and using) and environment variable values like |
This is probably some more legacy that can be handled separately. The environment variables prefixed with |
@rwilson-release What we CAN (technically) do and what we ACTUALLY do are not always the same. As a project, we have a pretty firm stance that we DO NOT CHANGE default behaviors, unless the benefit vastly outweighs the cost. We have a sort of "budget" for disruptive changes, and we need to spend it wisely because it is very slow to replenish. You also need to consider that some huge fraction of Kube users are on managed services, which can and do upgrade clusters without notifying users. As such, consider this:
How unhappy are you? Who are you unhappy with? When your provider says "Oh, that's because Kube v1.31 changed a default", do you feel like you trust Kubernetes MORE or LESS?
Maybe. We simply do not have data on it, so we err on the side of caution. The risk of breaking the above user is, IMO, higher than the benefit of having a cleaner default. We didn't invent this format, we stole it from Docker. Perhaps we wish we had not (I wish we had not), but we did, and it's been a "feature" for almost 10 years. Lots of time to pick up some users. WE DON'T BREAK USERS (without REALLY REALLY good reasons). Even if we think it's a dumb feature. Even if we think it imposes some hardship on people who want a sane default. Even if we suspect that nobody in their right mind uses it. |
I think that's fine and great and I don't disagree. I do think there is a way to move forward that isn't as bad as you describe it, but I could be wrong. I can only pray and hope we find a way to make changes without requiring huge monumental waterfall breaks I guess. |
I once believed that we could declare a deprecation loudly enough that it would be OK to change defaults within an API version. I no longer believe that. Some people don't read announcement blogs or CHANGELOGS. They don't subscribe to this GitHub repo. They don't follow me on Twitter. They don't even read urgent bulletins from their cloud-providers. They don't see API warnings (they either gloss right over them or they are buried inside CD system logs for "succeeded" runs). I have yet to find a vector which will get close enough to 100% that we could do this. And even if they DO see it, we're asking them to update their PERFECTLY GOOD deployments, which incurs testing and requalification, and generally just eats time. For what benefit? We have (rarely) changed things in this way but it takes SO MUCH effort, that the impact has to be dramatic. Like "could make the front page of the New York Times" dramatic.
Well, we have a way, it's just monumental in its scope and the pressure to do it has not reached critical - we create a core/v2 API. That's where we can change defaults (among other things). Users of core/v1 can remain blissfully ignorant. People who care can opt-in to using v2 on a case-by-case basis. I personally think we should do it, but I am not signing up to do the work right now - we have a lot of things more pressing that this. :( |
We have the luxury of generating manifests for our customers, so we've rolled out a global default for their manifests and our corner of the world operates a little bit better maybe. It occurs to me that if/when you are going to have a major revision to core/v2 API that you should just remove the feature completely rather than set the default. After all, removing all of that code and magical behaviour would make more sense and presumably add more benefits and value than simply changing a default value. That's my vote at least. Thanks for your attention. |
The way our API machinery works is that API versions are just "lenses" into the underlying data. Removing it from v2 means removing it from v1, and we don't do that. :( Trust me, there's nobody who wants to delete this more than me, but... |
This is legacy feature which contaminates environment variables with docker-compatible references to all services in namespace. Link: https://kubernetes.io/docs/tutorials/services/connect-applications-service/#accessing-the-service Link: kubernetes/kubernetes#121787
This is legacy feature which contaminates environment variables with docker-compatible references to all services in namespace. Link: https://kubernetes.io/docs/tutorials/services/connect-applications-service/#accessing-the-service Link: kubernetes/kubernetes#121787
This is legacy feature which contaminates environment variables with docker-compatible references to all services in namespace. Link: https://kubernetes.io/docs/tutorials/services/connect-applications-service/#accessing-the-service Link: kubernetes/kubernetes#121787
What would you like to be added?
I want to make enableServiceLinks disabled by default.
Why is this needed?
Service link environment variables are injected into every pod. It creates three environment variables for every service in a respective pod's namespace, regardless of how they are related. This behavior was observed in EKS 1.24.
In larger namespaces, this can cause pods to crash due to too many environmental variables. I assume this is due to Container runtime or Operating System Limitations.
I assume this was needed for legacy network reasons or installs that do not run cluster DNS. Regardless, Cluster DNS is added by default for most Kubernetes installers (excluding mircok8s) out there today.
I am willing to contribute if this is the direction we want to go.
The text was updated successfully, but these errors were encountered: