Skip to content
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

Add annotations for controlling request rate limiting #4660

Merged
merged 5 commits into from
Jan 9, 2024

Conversation

dbaumgarten
Copy link
Contributor

Proposed changes

This implements #4603.
Ingress resources can now have annotations to control request-rate-limiting.

Key points:

  • Rate-limits apply per ingress object (all routes/paths of an ingress share a common limit_req_zone and have common settings)
  • Supports different limits per path using minions. (Each mergeable minion can have separate rate-limiting configuration. Each minion uses it's own zone.
  • By default, no rate-limit is applied. limit_req_status defaults to 429. Zone size defaults to 10m.

Checklist

Before creating a PR, run through this checklist and mark each as complete.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works
  • I have checked that all unit tests pass after adding my changes
  • I have updated necessary documentation
  • I have rebased my branch onto main
  • I will ensure my PR is targeting the main branch and pulling from my branch from my own fork

@dbaumgarten dbaumgarten requested review from a team as code owners November 16, 2023 14:46
@github-actions github-actions bot added documentation Pull requests/issues for documentation enhancement Pull requests for new features/feature enhancements labels Nov 16, 2023
@vepatel vepatel linked an issue Nov 16, 2023 that may be closed by this pull request
@jjngx
Copy link
Contributor

jjngx commented Nov 27, 2023

@dbaumgarten could you please fix conflicts and push updates?

@jjngx jjngx self-assigned this Jan 5, 2024
@jjngx
Copy link
Contributor

jjngx commented Jan 5, 2024

@dbaumgarten could you please resolve conflicts and push updates?

@haywoodsh
Copy link
Contributor

Hi @dbaumgarten I pulled down your PR and it worked well!

One suggestion I have is that you can align the annotation names to the corresponding fields of the existing VirtuaServer rateLimit policy instead of the underlying NGINX directives, e.g. nginx.org/limit-req can be nginx.org/limit-req-rate, and nginx.org/limit-req-status can be nginx.org/limit-req-reject-code. What do you think?

Another thing I noticed is that, the key of limit_req_zone is hardcoded to $binary_remote_addr, unlike in the virtualserver policy where it is configurable, as well as other fields like dryRun and logLevel are available as configurable annotations. Is there any plan to include them in this PR?

@jjngx jjngx removed their assignment Jan 5, 2024
Copy link
Contributor

@jjngx jjngx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left one question regarding validation.

internal/configs/ingress_test.go Outdated Show resolved Hide resolved
@dbaumgarten
Copy link
Contributor Author

@haywoodsh aligning the annotations with the keys of VirtualServer sounds like a good idea. Will do.
Making the key for limit_req_zone configurable sounds like a good idea.
For my first draft I wanted to keep the number of added annotations to a minimum.
But if you think dryRun and LogLevel would be useful I can add these.

@jjngx Validating if the string ends in a proper unit should be pretty simple. Necessary or not it might save some people some headaches

@jjngx
Copy link
Contributor

jjngx commented Jan 8, 2024

@dbaumgarten thank you for contributing!

Could you please add validators and positive and negative tests for requests limiting and zone sizes annotations? The rules (suffixes) are listed here.
Please reach out if you need assistance.

cc @haywoodsh @j1m-ryan @vepatel

@j1m-ryan
Copy link
Member

j1m-ryan commented Jan 8, 2024

Hi @dbaumgarten, heres info from some manual testing I did which should help you in the validation for the nginx.org/limit-req-rate annotation
The rate argugment can accept two types of values r/s (requests per second) and r/m (requests per minute). The other time intervals will be rejected by nginx (for example r/ms requests per millisecond or r/h requests per hour would not be valid).
If no requests per time-interval is specificed, it assumes it is r/s, however, for the validation in NIC, I'd be happy if we were explicit in requiring either r/s or r/m for this annotation.
As a last piece of validation ensure the number before r/s or r/m is a whole number greater than 0. Thanks again.

Copy link

netlify bot commented Jan 9, 2024

👷 Deploy request for nginx-kubernetes-ingress pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit ce6f774

@dbaumgarten
Copy link
Contributor Author

Hi,
PR has been rebased, annotations are aligned with the virtual-server resource and validations have been added

Copy link

codecov bot commented Jan 9, 2024

Codecov Report

Attention: 21 lines in your changes are missing coverage. Please review.

Comparison is base (38a03fa) 52.11% compared to head (b26fb39) 52.31%.
Report is 7 commits behind head on main.

❗ Current head b26fb39 differs from pull request most recent head ce6f774. Consider uploading reports for the commit ce6f774 to get more accurate results

Files Patch % Lines
internal/configs/annotations.go 68.42% 7 Missing and 11 partials ⚠️
internal/configs/parsing_helpers.go 81.25% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4660      +/-   ##
==========================================
+ Coverage   52.11%   52.31%   +0.19%     
==========================================
  Files          60       60              
  Lines       17394    17501     +107     
==========================================
+ Hits         9065     9155      +90     
- Misses       8011     8018       +7     
- Partials      318      328      +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@j1m-ryan
Copy link
Member

j1m-ryan commented Jan 9, 2024

Hi @dbaumgarten, looks good to me so far. Just failing the lint. Can you install pre-commit (via pip or brew), the run pre-commit install in your repo. It picked up a couple small formatting things.

  Error: cyclomatic complexity 18 of func `parseRateLimitAnnotations` is high (> 15) (gocyclo)
  Error: File is not `gofumpt`-ed (gofumpt)
  Error: `Occuring` is a misspelling of `Occurring` (misspell)
  Error: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors (errorlint)
  Error: non-wrapping format verb for fmt.Errorf. Use `%w` to format errors (errorlint)```

@dbaumgarten
Copy link
Contributor Author

I fixed the linter-findings.
However I "fixed" the too-high complexity of parseRateLimitAnnotations by simply excluding it from gocyclo, as I don't really see any value in splitting it up.
Is that okay?

@j1m-ryan
Copy link
Member

j1m-ryan commented Jan 9, 2024

I'm ok with this @dbaumgarten as the cyclometric complexity is coming from linear if's, rather than nested ifs, and this feature had a lot of annotations. So thats fine IMO.

As @jjngx pointed out, can you change the t.Errorf's to t.Error's, where you are not using format strings. Theres still a few examples of this in annotations_test.go

Other than that its good to go imo

@dbaumgarten
Copy link
Contributor Author

Okay, I hope I found all remaining t.Errorfs ^^

Copy link
Contributor

@jjngx jjngx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻 thanks for contributing @dbaumgarten

Copy link
Contributor

@ADubhlaoich ADubhlaoich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM on the documentation side.

@dbaumgarten
Copy link
Contributor Author

There is so much going on on main, the PR is effectively always outdated...

@jjngx jjngx merged commit cb42312 into nginxinc:main Jan 9, 2024
73 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Pull requests/issues for documentation enhancement Pull requests for new features/feature enhancements
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Support rate-limiting for ingress-resources
5 participants