-
Notifications
You must be signed in to change notification settings - Fork 5.1k
listener: support multiple addresses #19367
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
Conversation
CC @envoyproxy/api-shepherds: Your approval is needed for changes made to |
This is a very rough PoC yet. Maybe it is ok for a high-level review. Appreciate any comments and suggestions! anyway, I will update it in 2022! |
can we shared same |
Most of the things should be able to share except the stats, Each address should have its own stats, which managed by ActiveListener. |
Consider how this interacts with stat_prefix on the listener. We may want to allow configuring a stat_prefix for each address. |
got it, thanks! |
1b2bf35
to
eb34df1
Compare
/wait Still work-in-progress |
eb34df1
to
adbb989
Compare
/wait still WIP |
/wait still working on the tests |
/wait The major code was finished, and should passed all the existing tests. Need to add new tests for new functionality. |
/wait |
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
/retest |
Retrying Azure Pipelines: |
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
/retest |
Retrying Azure Pipelines: |
Signed-off-by: He Jie Xu <hejie.xu@intel.com>
@@ -107,8 +107,15 @@ message Listener { | |||
// that is governed by the bind rules of the OS. E.g., multiple listeners can listen on port 0 on | |||
// Linux as the actual port will be allocated by the OS. | |||
// Required unless *api_listener* or *listener_specifier* is populated. | |||
// TODO (soulxu): deprecated the `address` field after `addresses` implemented. |
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.
I didn't mark the old field as deprecated
now since it will required to modify a lot of example config and test to not use the depcreated field, that will increase this PR size again and making the review harder. But let me know if we have better procedure for this case.
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.
I suggest splitting this PR, to a few PRs.
You can start by adding the addresses
field, mark in not-implemented-hide, and gradually add additional parts of the implementation.
At the end, there should be a well-defined behavior of what happens when both fields (address
and addresses
) are provided.
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.
Thanks! got it. I will mark it as not-implemented-hide
, and separate the API change out.
For other parts, also want to hear others' opinions if they are happy to separate the PR, since before people may want to see the full picture. I'm ok with both ways, if we want to separate the whole thing, I will work on it.
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.
Given that literally every envoy configuration uses these fields, we'll want to support both the old and the new forever. And I'd adopt the semantic that it's a config load error if both of them are set. So it logically turns into a oneof
between the two, but without modifying the old proto field.
As far as separating the PR or doing it all at once, I'm fine either way. I like seeing how the config will all be put together in one shot, but if the PR gets too big for that I'm fine splitting it. It may be worth defining the entire proto, but just not writing all the code yet, which should be fine if it's not-implemented-hide
.
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.
Given that literally every envoy configuration uses these fields, we'll want to support both the old and the new forever. And I'd adopt the semantic that it's a config load error if both of them are set. So it logically turns into a
oneof
between the two, but without modifying the old proto field.
I tend to agree with this, but from previous experience, when a configuration server supports both "old" and "new" Envoy clients, and sends them the same config, then the "new" clients will reject it.
One thing we can do is have a runtime guard against the rejection of configs that include both fields, and eventually remove that check.
If oneof
is the desired goal, consider adding oneof_promotion
tag.
As far as separating the PR or doing it all at once, I'm fine either way. I like seeing how the config will all be put together in one shot, but if the PR gets too big for that I'm fine splitting it. It may be worth defining the entire proto, but just not writing all the code yet, which should be fine if it's
not-implemented-hide
.
If possible, I think that it makes sense to break this to multiple smaller PRs (not only API vs non-API) to make it more reviewable. That said, if the PR includes mostly new tests, then it should be ok.
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.
I tend to agree with this, but from previous experience, when a configuration server supports both "old" and "new" Envoy clients, and sends them the same config, then the "new" clients will reject it.
In this case, I think it could be as simple as if there is only one address, config server populates the old field. If there are multiple addresses, config server populates the new field. If config server doesn't know if the client supports the new field, it can do the old behavior of completely duplicate listeners (filter chains etc) except with a different address.
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.
I tend to agree with this, but from previous experience, when a configuration server supports both "old" and "new" Envoy clients, and sends them the same config, then the "new" clients will reject it. One thing we can do is have a runtime guard against the rejection of configs that include both fields, and eventually remove that check. If
oneof
is the desired goal, consider addingoneof_promotion
tag.
I also have thing about keeping the old address
field and adding a new one called additional_addresses
. I haven't too much difference with one_of
way. Only one thing is if the user doesn't specify the stat_prefix
, then we fallback to use address
field as stat_prefix. For the oneof
case, if only the addresses
specified, then choose the first one as the stat_prefix. The additional_addresses
way has a little better sematic here.
As far as separating the PR or doing it all at once, I'm fine either way. I like seeing how the config will all be put together in one shot, but if the PR gets too big for that I'm fine splitting it. It may be worth defining the entire proto, but just not writing all the code yet, which should be fine if it's
not-implemented-hide
.If possible, I think that it makes sense to break this to multiple smaller PRs (not only API vs non-API) to make it more reviewable. That said, if the PR includes mostly new tests, then it should be ok.
Let me see what the separate PR looks like. I found I can't change ListenerImpl
and ListenerManagerImpl
separately, since our unit-tests test them together. And we can live this PR here for people who want to see the whole picture.
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.
Let me see what the separate PR looks like. I found I can't change
ListenerImpl
andListenerManagerImpl
separately, since our unit-tests test them together. And we can live this PR here for people who want to see the whole picture.
Just to clarify, breaking to multiple PRs is not a must, and in some cases it may make sense to have everything in one PR.
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.
I should be able to separate the PR as the commits have in the PR (maybe merge a few of them together) https://github.com/envoyproxy/envoy/pull/19367/commits, I checked each of major commit has unittest covered. I will merge those cleanup and format change commits in the bottom to the top commits. The last PR should be for the integration tests. Let me know if you guys happy with that.
// to listen on port 0, then this address has the port that was allocated by the OS. | ||
config.core.v3.Address local_address = 2; | ||
repeated config.core.v3.Address local_addresses = 2; |
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.
Do we have backward-compatibility rule for the admin API?
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.
yes, this is a breaking change, and will not be approved.
@mattklein123 I think this PR is ready for review. I updated the description for this PR #19367 (comment) hope that can help the review. Thanks for your review in advance! /assign @mattklein123 |
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.
Thanks for adding multiple addresses!
Left a few API comments.
@@ -26,7 +26,7 @@ message ListenerStatus { | |||
// Name of the listener | |||
string name = 1; | |||
|
|||
// The actual local address that the listener is listening on. If a listener was configured | |||
// The actual local addresses that the listener is listening on. If a listener was configured |
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.
I think this v2 should not be modified.
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.
yea, I modify the wrong file and then forget to revert back.
// to listen on port 0, then this address has the port that was allocated by the OS. | ||
config.core.v3.Address local_address = 2; | ||
repeated config.core.v3.Address local_addresses = 2; |
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.
yes, this is a breaking change, and will not be approved.
@@ -107,8 +107,15 @@ message Listener { | |||
// that is governed by the bind rules of the OS. E.g., multiple listeners can listen on port 0 on | |||
// Linux as the actual port will be allocated by the OS. | |||
// Required unless *api_listener* or *listener_specifier* is populated. | |||
// TODO (soulxu): deprecated the `address` field after `addresses` implemented. |
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.
I suggest splitting this PR, to a few PRs.
You can start by adding the addresses
field, mark in not-implemented-hide, and gradually add additional parts of the implementation.
At the end, there should be a well-defined behavior of what happens when both fields (address
and addresses
) are provided.
// A list of addresses that the listener should listen on. In general, the address must be unique, though | ||
// that is governed by the bind rules of the OS. E.g., multiple listeners can listen on port 0 on | ||
// Linux as the actual port will be allocated by the OS. For multiple addresses in single listener, | ||
// all addresses are the same protocol, and multiple internal addresses don't support now. |
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.
// all addresses are the same protocol, and multiple internal addresses don't support now. | |
// all addresses use the same protocol, and multiple internal addresses are not yet supported. |
@adisuissa thanks for the review! |
Is this PR ready for full review? Also, this is very big. Is there any way to split this into smaller chunks? Thank you. /wait-any |
Yes, this is ready for a full review. Now we have two votes on the split PR, then let me split it. Also, the API change already separated out #21391, appreciate the review and feedback! |
This pull request has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
This pull request has been automatically closed because it has not had activity in the last 37 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
Commit Message: listener: support multiple addresses
Additional Description:
This PR adds the ability of the listener to support multiple listening addresses.
The new field
addresses
was added to Listener API. The additional listening addresses can be added. Each address should be unique, and all the addresses should be the same protocol. The Envoy Internal address won't support this implementation since there is no use case for now, but it can be added in the future.The
ListenerImpl
,ListenerManagerImpl
, andConnectionHandlerImpl
will be aware of the multiple addresses. TheListenerImpl
will contains multiple addresses and the corresponding socket factories.ListenerManagerImpl
will be aware of the multiple addresses when adding or updating the listener.ConnectionHandlerImpl
is responsible for creating theActiveListener
for each address.The
ActiveListener
for UDP and TCP won't be aware of the multiple addresses, eachActiveListener
will listen to a single address as before. We also can consider oneActiveListener
to serve multiple addresses, which will need more change. If this is needed, we can do this in the future.The
ListenerImpl
will createConnectionBalancer
andUdpWorkerRouter
for each address. TheActiveTcpListener
andActiveUdpListener
will reference to the address-specific balancer and worker router.Also, the admin API
/listeners
is changed to support returning of multiple addresses.Risk Level: high
Testing: unit tests and integration tests added
Docs Changes: API doc
Release Notes: new feature
Platform Specific Features: no
Fixes #11184