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 global rate limiting support #3298

Merged
merged 4 commits into from Feb 19, 2021

Conversation

skriss
Copy link
Member

@skriss skriss commented Feb 1, 2021

Adds support for configuring an external Rate Limit
Service (RLS) that is used for making global rate
limit decisions. Adds support to HTTPProxy for
global rate limit policies, that generate descriptors
for requests to be sent to the RLS for rate-limit
decisions.

Closes #370.

Signed-off-by: Steve Kriss krisss@vmware.com

@skriss skriss added this to the 1.13.0 milestone Feb 1, 2021
@codecov
Copy link

codecov bot commented Feb 1, 2021

Codecov Report

Merging #3298 (8fd4f79) into main (d31d2b6) will increase coverage by 0.22%.
The diff coverage is 89.01%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3298      +/-   ##
==========================================
+ Coverage   75.54%   75.77%   +0.22%     
==========================================
  Files          98       98              
  Lines        6417     6535     +118     
==========================================
+ Hits         4848     4952     +104     
- Misses       1460     1475      +15     
+ Partials      109      108       -1     
Impacted Files Coverage Δ
cmd/contour/serve.go 0.00% <0.00%> (ø)
internal/dag/dag.go 96.80% <ø> (ø)
internal/dag/extension_processor.go 94.52% <100.00%> (ø)
internal/dag/httpproxy_processor.go 91.56% <100.00%> (ø)
internal/dag/policy.go 96.98% <100.00%> (+0.47%) ⬆️
internal/envoy/v3/ratelimit.go 100.00% <100.00%> (+8.33%) ⬆️
internal/envoy/v3/route.go 98.92% <100.00%> (+0.01%) ⬆️
internal/featuretests/v3/envoy.go 100.00% <100.00%> (ø)
internal/xdscache/v3/listener.go 95.58% <100.00%> (+0.18%) ⬆️
internal/xdscache/v3/route.go 84.32% <100.00%> (+0.23%) ⬆️
... and 2 more

@skriss skriss force-pushed the global-rate-limiting branch 4 times, most recently from 5131308 to dc96013 Compare February 4, 2021 22:54
@skriss
Copy link
Member Author

skriss commented Feb 4, 2021

@stevesloka @youngnick @sunjayBhatia I'd appreciate an initial review on this. I am still working on documentation.

@skriss skriss added the release-note Denotes a PR that will be considered when it comes time to generate release notes. label Feb 4, 2021
@skriss skriss force-pushed the global-rate-limiting branch 4 times, most recently from 9cdc0ea to f535ccf Compare February 9, 2021 17:22
@skriss skriss changed the title [WIP] add global rate limiting support add global rate limiting support Feb 9, 2021
@skriss skriss marked this pull request as ready for review February 9, 2021 17:23
@skriss skriss requested a review from a team as a code owner February 9, 2021 17:23
@skriss
Copy link
Member Author

skriss commented Feb 9, 2021

Ran through a full test of the guide, fixed a couple small things.

Copy link
Member

@sunjayBhatia sunjayBhatia left a comment

Choose a reason for hiding this comment

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

Looks good overall! Lots of changes but you're right mostly generated etc.

Just a couple small comments

site/docs/main/config/api-reference.html Outdated Show resolved Hide resolved
Domain string `yaml:"domain,omitempty"`

// FailOpen defines whether to allow requests to proceed when the
// Rate Limit Service fails to respond properly.
Copy link
Member

Choose a reason for hiding this comment

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

nit: Maybe define properly? (timeout etc.)

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 also reminds me I forgot to add to site/docs/main/configuration.md and the example config file, will do that as well.

AllowChunkedLength(v.ListenerConfig.AllowChunkedLength).
NumTrustedHops(v.ListenerConfig.XffNumTrustedHops)

if rlc := v.RateLimitConfig; rlc != nil {
Copy link
Member

Choose a reason for hiding this comment

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

nit: Could this be collapsed so we don't need to add the if (here and above)?

e.g. envoy_v3.GlobalRateLimitFilter could take just a RateLimitConfig and do the nil check there? and builder.AddFilter does nothing if it gets nil?

Copy link
Member Author

@skriss skriss Feb 10, 2021

Choose a reason for hiding this comment

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

Yeah good idea, that'd clean this up; though as-is that would create an import cycle so need to re-jigger things a bit.

@@ -294,6 +296,36 @@ func doServe(log logrus.FieldLogger, ctx *serveContext) error {
XffNumTrustedHops: ctx.Config.Network.XffNumTrustedHops,
}

if ctx.Config.RateLimitService.ExtensionService != "" {
namespacedName := k8s.NamespacedNameFrom(ctx.Config.RateLimitService.ExtensionService)
Copy link
Member

Choose a reason for hiding this comment

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

Would it make sense to pull this sort of logic (fetching a service/checking for existence/getting some spec params) into a common helper? I'm thinking this logic could possibly be duplicated elsewhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

The existing extension service code gets its ExtensionService via the DAG cache, so it's a different code path / not really duplicated with this logic. Maybe we can keep an eye on this for refactoring when we add our next extension service impl.

@sunjayBhatia sunjayBhatia added this to In progress in Contour Project Board via automation Feb 11, 2021
@sunjayBhatia sunjayBhatia moved this from In progress to 1.13 Release in Contour Project Board Feb 11, 2021
Copy link
Member

@stevesloka stevesloka left a comment

Choose a reason for hiding this comment

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

Overall looks great to me @skriss! Just a couple questions / thoughts.

// ensure the specified ExtensionService exists
res, err := client.Get(context.Background(), namespacedName.Name, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("error getting rate limit extension service %s: %v", namespacedName, err)
Copy link
Member

Choose a reason for hiding this comment

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

Should this be a fatal error or not configure rate limiting until the extension service exists?

Copy link
Member Author

Choose a reason for hiding this comment

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

Agree it's not ideal to require the extension service to exist at startup. I think we could change the flow somewhat to resolve the extension service ref during the DAG build instead. If it's OK with you, I'll file a follow-up issue to look at that?

Copy link
Member

Choose a reason for hiding this comment

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

yup sure thing!

@@ -99,3 +99,7 @@ data:
# Configure the number of additional ingress proxy hops from the
# right side of the x-forwarded-for HTTP header to trust.
# num-trusted-hops: 0
# rateLimitService:
# extensionService: projectcontour/ratelimit
Copy link
Member

Choose a reason for hiding this comment

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

We have comments for other bits in this config explaining what they mean, maybe match that a bit?

Copy link
Member Author

Choose a reason for hiding this comment

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

added

@@ -0,0 +1,11 @@
apiVersion: v1
Copy link
Member

Choose a reason for hiding this comment

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

Not sure if we should include this or just reference what to setup. I guess it's a nice copy/paste way to follow a guide so probably good.


## Deploy an RLS

For this guide, we'll deploy the [Envoy rate limit service][4] as our RLS.
Copy link
Member

Choose a reason for hiding this comment

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

Maybe just give a couple more sentences on how the RLS works just so it's clear what is happening? (i.e. The RLS uses a Redis cache internally. Blah blah?)

Copy link
Member Author

Choose a reason for hiding this comment

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

copied an excerpt from the Envoy RLS README to give some more color.

site/docs/main/config/rate-limiting.md Show resolved Hide resolved
Copy link
Member

@youngnick youngnick left a comment

Choose a reason for hiding this comment

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

LGTM, nice work.

// ensure the specified ExtensionService exists
res, err := client.Get(context.Background(), namespacedName.Name, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("error getting rate limit extension service %s: %v", namespacedName, err)
Copy link
Member

Choose a reason for hiding this comment

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

If this is not fatal, then we need instead to do this similarly to the Envoy service status watcher - a separate goroutine that looks for the defined ExtensionService and sets up the config once it exists and is working.

I'd say that's quite a bit of extra work for minimal gain. If you're configuring the feature, you should have access to restart Contour, and you should be able to ensure everything is set up correctly.

Copy link
Member Author

Choose a reason for hiding this comment

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

See #3298 (comment), I think we could make some improvements here but I'm not considering it blocking.

@skriss skriss force-pushed the global-rate-limiting branch 2 times, most recently from 07a9a10 to 5036185 Compare February 17, 2021 16:45
@skriss
Copy link
Member Author

skriss commented Feb 17, 2021

I believe I've addressed everyone's review comments now, please take another look!

Adds support for configuring an external Rate Limit
Service (RLS) that is used for making global rate
limit decisions. Adds support to HTTPProxy for
global rate limit policies, that generate descriptors
for requests to be sent to the RLS for rate-limit
decisions.

Closes projectcontour#370.

Signed-off-by: Steve Kriss <krisss@vmware.com>
Signed-off-by: Steve Kriss <krisss@vmware.com>
Signed-off-by: Steve Kriss <krisss@vmware.com>
Signed-off-by: Steve Kriss <krisss@vmware.com>
@stevesloka stevesloka merged commit 4fafe5f into projectcontour:main Feb 19, 2021
@skriss
Copy link
Member Author

skriss commented Feb 19, 2021

😅

iyacontrol pushed a commit to iyacontrol/contour that referenced this pull request Feb 23, 2021
Adds support for configuring an external Rate Limit
Service (RLS) that is used for making global rate
limit decisions. Adds support to HTTPProxy for
global rate limit policies, that generate descriptors
for requests to be sent to the RLS for rate-limit
decisions.

Closes projectcontour#370.

Signed-off-by: Steve Kriss <krisss@vmware.com>
Signed-off-by: iyacontrol <gaohj2015@yeah.net>
@skriss skriss deleted the global-rate-limiting branch February 24, 2021 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-note Denotes a PR that will be considered when it comes time to generate release notes.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[feature] Add rate limiting support
4 participants