-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Simplify Opaque Port Manifests #9803
Comments
Just incase I'm misunderstanding, are you aware that the opaque-port annotation accepts a range, so |
@dwilliams782 good question. The issue presents specifically when port-ranges are used. With massive ranges each port in the range is added to the manifest which is then expanded to the point where it can 1. make the config and annotations a nightmare to manage, 2. increase proxy mem usage, and 3. overwhelm the k8s api due to the massive character count that is added to some events/requests. |
Depends on #2079 Currently, the `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` environment variable accepts a comma-delimited list of individual port numbers. Each of these ports is then stored as a separate cache entry in the port policy cache to indicate that the port is opaque. Unfortunately, this does not work well when a very large number of ports are marked as opaque, because the proxy-injector will generate a massive value for that environment variable, listing every individual port. This can cause issues when this manifest becomes larger than the Kubernetes API can reasonably handle. In addition, huge numbers of ports will all be kept in memory as a separate cache entry by the proxy, increasing proxy memory usage. See linkerd/linkerd2#9803 for details. This branch changes the proxy so that the `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` environment variable may contain a list of individual port numbers *and* port ranges, which are specified as `<low>-<high>`. Opaque ports are now stored using a `RangeInclusiveSet` from the `rangemap` crate, rather than by creating individual cache entries for each port. This means we are no longer storing a separate entry in the cache for every port in a range, reducing memory consumption when there are very large ranges of opaque ports. This is the proxy half of the work towards resolving linkerd/linkerd2#9803. Once this branch lands, we'll also have to change the proxy-injector so that it no longer handles opaque port ranges by generating a list of all the individual ports in the range, and simply forwards those ranges as they were specified when generating the environment variable.
inbound: Remove default policies (#2204) When an inbound proxy accepts a connection, it needs a policy for the inbound port. If there is no known policy, then a default inbound policy is provided from the proxy's configuration. This presents a few problems: * The server-configured policy may be more restrictive than the default policy. This could all unauthorized connections to race into a pod (when ports are not documented in the the pod spec). * The server-configured protocol configuration may differ from the proxy's configuration. * The way the proxy reads environment configuration for default policies is inefficient for large port ranges. See linkerd/linkerd2#9803 ## Solution To simplify the proxy's configuration surface area, we remove synthetic default policy configurations so that all inbound policies are provided by the policy controller. This means that the proxy will require either a cached policy or a response from the policy controller before it can accept a connection. Proxies always discover and retain cached policies for all ports documented in `LINKERD2_PROXY_INBOUND_PORTS`. Other policies are discovered dynamically and cached for the discovery idle timeout. This inbound proxy now requires a policy controller client configuration. Tests are updated to use a mock policy controller service. The following environment variables are no longer used: * `LINKERD2_PROXY_INBOUND_PORTS_REQUIRE_IDENTITY` * `LINKERD2_PROXY_INBOUND_PORTS_REQUIRE_TLS` * `LINKERD2_PROXY_INBOUND_DEFAULT_POLICY` * `LINKERD2_PROXY_POLICY_CLUSTER_NETWORKS See also #2186
Proxy PR linkerd/linkerd2-proxy#2395 changes the proxy to accept port ranges in the |
…2395) The proxy injector populates an environment variable, `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION`, with a list of all ports marked as opaque. Currently, however, _the proxy _does not actually use this environment variable_. Instead, opaque ports are discovered from the policy controller. The opaque ports environment variable was used only when running in the "fixed" inbound policy mode, where all inbound policies are determined from environment variables, and no policy controller address is provided. This mode is no longer supported, and the policy controller address is now required, so the `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` environment variable is not currently used to discover inbound opaque ports. There are two issues with the current state of things. One is that inbound policy discovery is _non-blocking_: when an inbound proxy receives a connection on a port that it has not previously discovered a policy for, it uses the default policy until it has successfully discovered a policy for that port from the policy controller. This means that the proxy may perform protocol detection on the first connection to an opaque port. This isn't great, as it may result in a protocol detection timeout error on a port that the user had previously marked as opaque. It would be preferable for the proxy to read the environment variable, and use it to determine whether the default policy for a port is opaque, so that ports marked as opaque disable protocol detection even before the "actual" policy is discovered. The other issue with the `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` environment variable is that it is currently a list of _individual port numbers_, while the proxy injector can accept annotations that specify _ranges_ of opaque ports. This means that when a very large number of ports are marked as opaque, the proxy manifest must contain a list of each individual port number in those ranges, making it potentially quite large. See linkerd/linkerd2#9803 for details on this issue. This branch addresses both of these problems. The proxy is changed so that it will once again read the `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` environment variable, and use it to determine which ports should have opaque policies by default. The parsing of the environment variable is changed to support specifying ports as a list of ranges, rather than a list of individual port numbers. Along with a proxy-injector change, this would resolve the manifest size issue described in linkerd/linkerd2#9803. This is implemented by changing the `inbound::policy::Store` type to also include a set of port ranges that are marked as opaque. When the `Store` handles a `get_policy` call for a port that is not already in the cache, it starts a control plane watch for that port just as it did previously. However, when determining the initial _default_ value for the policy, before the control plane discovery provides one, it checks whether the port is in a range that is marked as opaque, and, if it is, uses an opaque default policy instead. This approach was chosen rather than pre-populating the `Store` with policies for all opaque ports to better handle the case where very large ranges are marked as opaque and are used infrequently. If the `Store` was pre-populated with default policies for all such ports, it would essentially behave as though all ports in `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` were also in `LINKERD2_PROXY_INBOUND_PORTS`, and the proxy would immediately start a policy controller discovery watch for all opaque ports, which would be kept open for the proxy's entire lifetime. In cases where the opaque ports ranges include ~10,000s of ports, this causes significant unnecessary load on the policy controller. Storing opaque port ranges separately and using them to determine the default policy as needed allows opaque port policies to be treated the same as non-default ports, which are discovered as needed and can be evicted from the cache if they are unused. If a port is in both `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` *and* `LINKERD2_PROXY_INBOUND_PORTS`, the proxy will start discovery eagerly and retain the port in the cache forever, but the default policy will be opaque. I've also added a test for the behavior of opaque ports where the port's policy has not been discovered from the policy controller. That test fails on `main`, as the proxy attempts protocol detection, but passes on this branch. In addition, I changed the parsing of the `LINKERD2_PROXY_INBOUND_PORTS` environment variable to also accept ranges, because it seemed like a nice thing to do while I was here. :)
We've now merged the proxy release that modifies the proxy to accept ranges in the environment variable. I'm working on modifying the proxy-injector to actually emit ranges when patching a manifest. This is somewhat more complex than simply removing code that turns a list of ranges into a list of individual port numbers, though, because the proxy-injector also performs filtering of the opaque port list so that it includes only those ports actually exposed by the Service: Lines 376 to 427 in 5f7bbba
|
Currently, the proxy injector will expand lists of opaque port ranges into lists of individual port numbers. This is because the proxy has historically not accepted port ranges in the `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` environment variable. However, when very large ranges are used, the size of the injected manifest can be quite large, since each individual port number in a range must be listed separately. Proxy PR linkerd/linkerd2-proxy#2395 changed the proxy to accept ranges as well as individual port numbers in the opaque ports environment variable, and this change was included in the latest proxy release (v2.200.0). This means that the proxy-injector no longer needs to expand large port ranges into individual port numbers, and can now simply forward the list of ranges to the proxy. This branch changes the proxy injector to do this, resolving issues with manifest size due to large port ranges. Closes #9803
Currently, the proxy injector will expand lists of opaque port ranges into lists of individual port numbers. This is because the proxy has historically not accepted port ranges in the `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` environment variable. However, when very large ranges are used, the size of the injected manifest can be quite large, since each individual port number in a range must be listed separately. Proxy PR linkerd/linkerd2-proxy#2395 changed the proxy to accept ranges as well as individual port numbers in the opaque ports environment variable, and this change was included in the latest proxy release (v2.200.0). This means that the proxy-injector no longer needs to expand large port ranges into individual port numbers, and can now simply forward the list of ranges to the proxy. This branch changes the proxy injector to do this, resolving issues with manifest size due to large port ranges. Closes #9803
Currently, the proxy injector will expand lists of opaque port ranges into lists of individual port numbers. This is because the proxy has historically not accepted port ranges in the `LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` environment variable. However, when very large ranges are used, the size of the injected manifest can be quite large, since each individual port number in a range must be listed separately. Proxy PR linkerd/linkerd2-proxy#2395 changed the proxy to accept ranges as well as individual port numbers in the opaque ports environment variable, and this change was included in the latest proxy release (v2.200.0). This means that the proxy-injector no longer needs to expand large port ranges into individual port numbers, and can now simply forward the list of ranges to the proxy. This branch changes the proxy injector to do this, resolving issues with manifest size due to large port ranges. Closes #9803 Signed-off-by: Eric Anderson <eric@buoyant.io>
What problem are you trying to solve?
Currently our protocol detection opaque port markings are exclusive (i.e., we mark which ports we want to exclude from protocol detection), which creates issues for users who have to exclude massive port-ranges for integration with other infrastructure components such as syslog, for example. Adding massive ranges expands the manifest and we've seen issues where it also creates problems for the k8s api, not to mention the additional memory pressure on the proxies themselves which has to be accounted for.
The text was updated successfully, but these errors were encountered: