-
Notifications
You must be signed in to change notification settings - Fork 1
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 a hash function which doesnt rely on reflection for creating a… #23
base: section-v1
Are you sure you want to change the base?
Conversation
… hash of the nginx conf struct
ae54b96
to
8876db8
Compare
The file this is in was already created by us in a previous commit, its not part of the upstream ingress-nginx codebase |
@mwickman I recommend retaining the old reflection-based hashing code either in its current location, or moving it to a Additional, introduce benchmark tests demonstrating the justification of maintaining the hard-coded hashing function versus reflection-based. Finally, check github history for commit description and PR discussions about why they chose reflection-based hashing and so we can re-open any old debates with new arguments. |
|
||
writeAuthTLSConfig(l.BasicDigestAuth, hash) | ||
|
||
writeString(*l.Denied, hash) |
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 can segfault if Denied (pointer to string) is null (as I saw in testing earlier). The fix I implemented is in our debug branch.
@mwickman are you interested in pushing this change in the upstream project? |
It would be great to see this benchmark :)
No particular reason. It was the easiest solution, reusing the already available json tag in the structs. |
@aledbf It looks like the bulk of the problem is caused by the inclusion of the original k8s api ingress object on the location structs. In our use case we have many hundreds of host names on an k8s ingress definition, the hash has been seen to take more than 15 minutes to complete (in production). Setting that single field to be ignored reduces ~10+ minutes to ~10 seconds. e.g.
The existing hardcoded hash func in this PR is ~1 second (although I personally suspect much of that benefit is from skipping many members that the hash walker touches - e.g. it definitely doesn't touch the k8s ingress on location) |
Interesting. We have several users with more than 20000 ingresses and the issues they have are not related to the hash or reload times.
I am still interested in the upstream of this change :) |
@aledbf I think this might be that we have a smaller number of ingresses with a larger number of hosts per ingress. I'm very interested in users with 20000 ingresses, we're forked largely to avoid an nginx server block per hostname because of the per nginx server block memory overhead incurred (we couldn't use an nginx aliases annotation since certs wouldn't load as the cert CNs didn't match a explicit hostname). Are these 20000 ingresses with 20000 hostnames/certs? Or 20000 locations on a limited set of hostnames? Or do they just throw memory at it? (Actually, we've already realized that large numbers of hosts on a single ingress object is going to be a limitation, with etcd's 1MB object limits - which we'll hit at ~2000 hostnames on an ingress.) |
Thanks for this point.
I have a script that creates 5000 ingresses with different hostnames, one path and tls.
Another problem with this approach is that you cannot use annotations (they will be applied to all the hosts/paths) Please check |
What's the memory utilization you see with your use case? (nginx and go) |
@aledbf I'm definitely interested in merging this or some similar solution upstream. I'll need just a bit of time though to prep a PR from the latest master branch, I likely won't reuse this commit. |
@ivan-section-io is there an open issue describing all your requirements that are lacking in upstream ingress-nginx with a bit more details? How are you overcoming this in your fork, bundling all hosts in a single server block? Does that mean you are OK with not being able to customize settings per hostname?
Would it make sense to teach ingress-nginx to load certs based on aliases then? I'm asking this questions to identify if it'd make sense to support this case in upstream ingress-nginx. I've also been thinking of delegating route dispatching to Lua as well which would address your case as I understand. The idea would be to post server objects to Lua land as we do for certificates and backends. But this is a big change and will mean we won't be able to use some more stock Nginx directives. |
@ElvinEfendi No. We've largely just tweaked for our own needs, feeling they are outside the requirements of mainstream.
For each hostname "set", we use a single k8s ingress definition having an IngressRule for each hostname. The paths & backends for each IngressRule are all the same. We then use a custom template function to collapse servers by a common identifier (we hijacked
Yes (well, per group of hostnames). In fact, I believe we would have just used the
I certainly believe so. But, a "full" implementation is non-trivial. nginx
I believe - Yes. To me, |
This is being done here https://github.com/kubernetes/ingress-nginx/blob/f4678764f5b661b04c6678be4c2f2a13caf8710e/internal/ingress/controller/nginx.go#L1005 |
@aledbf I'm having trouble immediately seeing how that handles multiple hostnames? Where |
The link is for the CN validation of the alias.
Adding multiple aliases should be easy and not a breaking change. |
… hash of the nginx conf struct
I modeled this off of the function in type_equals.go which also walks the struct in order to determine equality.