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

Added upstream zone directive annotation #629

Merged
merged 7 commits into from
Jul 30, 2019
Merged

Conversation

vrrs
Copy link
Contributor

@vrrs vrrs commented Jul 22, 2019

Proposed changes

These changes enable the zone directive on upstream block with upstream name equal to zone name and zone size equals to the annotation value. This follow the same convention as nginx-plus ingress config. For instance, nginx.org/upstream-zone-size: "32k" in your ingress.yaml will generate a config such as

upstream myService-ingress-prod-myService.production.ingress.net-myService-prod-80 {
   zone myService-ingress-prod-myService.production.ingress.net-myService-prod-80 32k;
   server 125.255.255.255:8888 max_fails=3 fail_timeout=10 max_conns=6;
}

If the annotation is not present then the zone directive will not be present on the config.

Nginx Documentation for upstream zone

Syntax: zone name [size];
Default: N/A
Context: upstream

Motivation

In multi worker nginx setup(worker_processes > 1), the zone directive fixes the least_conn lb method as well as max_fails, max_conns parameters. From the nginx document on load balancing:

For example, if the configuration of a group is not shared, each worker process maintains its own counter for failed attempts to pass a request to a server (set by the max_fails parameter). In this case, each request gets to only one worker process. When the worker process that is selected to process a request fails to transmit the request to a server, other worker processes don’t know anything about it. While some worker process can consider a server unavailable, others might still send requests to this server. For a server to be definitively considered unavailable, the number of failed attempts during the timeframe set by the fail_timeout parameter must equal max_fails multiplied by the number of worker processes. On the other hand, the zone directive guarantees the expected behavior.
Similarly, the Least Connections load‑balancing method might not work as expected without the zone directive, at least under low load.

Use case

A properly working least_conn load balancer is very useful in balancing long lived connections and limiting load on the destination servers; particularly when upstream servers are streaming web apps.

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 master
  • I will ensure my PR is targeting the master branch and pulling from my branch from my own fork

@pleshakov pleshakov added the enhancement Pull requests for new features/feature enhancements label Jul 23, 2019
@pleshakov
Copy link
Contributor

@vrrs thanks for the PR! We'll review it shortly

@pleshakov
Copy link
Contributor

@vrrs
Thanks for bringing this PR! Having zones in the config for enabling passive health checks and the least conn algorithm to work across multiple workers for NGINX OSS makes sense. We should've had it implemented before.

I wonder though if it makes sense to have a configmap key upstream-zone-size instead of the suggestion annotation. It seems that it is a more common case for the zone size to be configured/enabled per all Ingress resources than an per individual Ingress resource. For example, if the Ingress Controller is configured with multiple NGINX workers, why not to enable zones for all Ingresses? Does that apply for your requirements as well?

Additionally, having zones enabled by default also makes sense, so that the mentioned benefits are enabled by default. The default size of 256K will work for the case of more than 100 endpoints in a single upstream. We use the same size in the upstreams of NGINX Plus. Having a special value 0 to remove the zones from upstreams is reasonable to me.

Let me know what you think.

@vrrs
Copy link
Contributor Author

vrrs commented Jul 24, 2019

@pleshakov Our use case requires individual resources to specify max_conn and zone since our ingress nginx is shared. Different set of upstream servers might require different zone sizes
or no zones at all. In addition, this change is backward compatible. We have already deployments without upstream zone and adding a default zone might have an impact on performance.
However, We can add a configmap key with a special value(0) as you suggested and set it to 0 as default. This way it covers both use cases.

In summary, We should add a configmap key along with the annotation defaulted to 0 which will enable both use cases of having all ingresses with one zone(using configmap key) or having individual ingresses with specific zones(with annotation).
Let me know what you think.

Copy link
Contributor

@pleshakov pleshakov left a comment

Choose a reason for hiding this comment

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

@vrrs

In addition, this change is backward compatible. We have already deployments without upstream zone and adding a default zone might have an impact on performance.

Thanks for thinking about backward compatibility! However, we do not expect any significant impact on performance. At the same time, we will document this change in the release notes appropriately, so that during upgrade people can set the configmap key to 0 to disable zones.

In summary, We should add a configmap key along with the annotation defaulted to 0 which will enable both use cases of having all ingresses with one zone(using configmap key) or having individual ingresses with specific zones(with annotation).

Sounds good! Just a small note -- the annotation should default to the ConfigMap key.
If you could make the default 256K and treat 0 as a special value to turn off the zones (both for the configmap key and the annotation), that be great!

I added suggestions about the doc (which assumes the configmap key, the default and the special value to turn off zones) and a small consistency suggestion for the template.

docs/configmap-and-annotations.md Outdated Show resolved Hide resolved
@@ -2,6 +2,7 @@

{{range $upstream := .Upstreams}}
upstream {{$upstream.Name}} {
{{if $upstream.UpstreamZoneSize }}zone {{$upstream.Name}} {{$upstream.UpstreamZoneSize}};{{end}}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{{if $upstream.UpstreamZoneSize }}zone {{$upstream.Name}} {{$upstream.UpstreamZoneSize}};{{end}}
{{if $upstream.UpstreamZoneSize}}zone {{$upstream.Name}} {{$upstream.UpstreamZoneSize}};{{end}}

@vrrs
Copy link
Contributor Author

vrrs commented Jul 25, 2019

@pleshakov Performed the changes

@vrrs
Copy link
Contributor Author

vrrs commented Jul 25, 2019

@Rulox @Dean-Coakley 👀 👀 --^

Copy link
Contributor

@Dean-Coakley Dean-Coakley 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!

Lgtm once: #629 (comment) is applied. Looks like it was missed.

@@ -166,6 +166,7 @@ spec:
| `nginx.org/websocket-services` | N/A | Enables WebSocket for services. | N/A | [WebSocket support](../examples/websocket). |
| `nginx.org/max-fails` | `max-fails` | Sets the value of the [max_fails](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#max_fails) parameter of the `server` directive. | `1` | |
| `nginx.org/max-conns` | N\A | Sets the value of the [max_conns](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#max_conns) parameter of the `server` directive. | `0` | |
| `nginx.org/upstream-zone-size` | N\A | Sets the size of the shared memory [zone](https://nginx.org/en/docs/http/ngx_http_upstream_module.html?#zone). If this annotation is not present then the zone directive will not be set. | `N\A` | |
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like you missed #629 (comment) unless I'm mistaken?

@@ -109,6 +110,7 @@ func NewDefaultConfigParams() *ConfigParams {
SSLPorts: []int{443},
MaxFails: 1,
MaxConns: 0,
UpstreamZoneSize: "256k",
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this is missing a run of gofmt, not gonna block the pr for it, but would be nice.

Copy link
Contributor

Choose a reason for hiding this comment

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

go fmt should be run for consistency before merging

@vrrs
Copy link
Contributor Author

vrrs commented Jul 26, 2019

@Dean-Coakley Modified the documentation.

@Dean-Coakley
Copy link
Contributor

@vrrs The format of config_params.go still isn't quite right.
Please run $ gofmt -w internal/configs/config_params.go

@vrrs
Copy link
Contributor Author

vrrs commented Jul 26, 2019

Ohh i see, check now @Dean-Coakley

Copy link
Contributor

@Dean-Coakley Dean-Coakley left a comment

Choose a reason for hiding this comment

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

Perfect! Thanks @vrrs

@Rulox
Copy link
Contributor

Rulox commented Jul 29, 2019

@vrrs Looks great, just 2 small things before I can merge:

  1. It seems this Added upstream zone directive annotation  #629 (comment) was missed? (it's just removing the space there)

  2. Make sure you follow the (style guides)[https://github.com/nginxinc/kubernetes-ingress/blob/master/CONTRIBUTING.md#git-style-guide]. You need to rebase against master and also squash all your commits into one, using a present tense commit message like Add upstream zone directive annotation/configmap.

Both changes are just to follow the rules and consistency with the rest of the code/repo.

Once that's done I will merge it, thanks again for your time!

@vrrs
Copy link
Contributor Author

vrrs commented Jul 29, 2019

@Rulox

  1. Done. FYI, the lbmethod upstream line is not following this standard which is the one i was following.
  2. Regarding squashed commits, when merging you can select squash and merge. I always rebase before submitting PRs and using one commit(From the guideline: Keep a clean, concise and meaningful git commit history on your branch, rebasing locally and squashing before submitting a PR). The extra commits you see were as a consequence of the review. This branch has no merge conflicts. Am i suppose to close this PR and create a new one ?

@Rulox
Copy link
Contributor

Rulox commented Jul 30, 2019

@vrrs

  1. Yes I noticed when reviewing, it's a mistake, I'll fix it.
  2. No worries, I'll squash them

👍

@Rulox Rulox merged commit 9739593 into nginx:master Jul 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Pull requests for new features/feature enhancements
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants