-
Notifications
You must be signed in to change notification settings - Fork 370
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 NodePort support for Antrea Proxy on Linux #1471
Conversation
Thanks for your PR. The following commands are available:
|
Codecov Report
@@ Coverage Diff @@
## main #1471 +/- ##
=======================================
Coverage ? 41.09%
=======================================
Files ? 116
Lines ? 14717
Branches ? 0
=======================================
Hits ? 6048
Misses ? 8148
Partials ? 521
Flags with carried forward coverage won't be shown. Click here to find out more. |
9108527
to
1b3b6dc
Compare
/test-all |
294c717
to
d734e2b
Compare
d734e2b
to
c0b7207
Compare
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 haven't finished review. But I did some test based on the patch and found an issue:
When scaling down backend pods, the members in openflow group doesn't change, leading to connectivity issue.
@@ -116,3 +119,13 @@ featureGates: | |||
# whenever a Pod's container defines a specific port to be exposed (each container can define a list of ports as pod.spec.containers[].ports), | |||
# and all Node traffic directed to that port will be forwarded to the Pod. | |||
#nplPortRange: 40000-41000 | |||
|
|||
# The virtual IP for NodePort Service support. It must be a link-local IP otherwise the Agents will report error. | |||
#nodePortVirtualIP: 169.254.169.110 |
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.
Have you tried policy route approach? I did an experiment and it worked as we discussed.
If NAT is not likely to be the final solution, better not to add this argument in case compatbility issue in future. We can just use a reserved IP in alpha phase I think.
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.
Why we care it must be link-local?
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.
@tnqn, I tried the policy route way.
If the destination is a loopback address we still need to do a DNAT. Considering this is an ALPHA feature for now, we can discuss it more in the future.
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.
@jianjuns, do you think we should use any forwardable address here?
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 want to understand the current design first. Why IPv4 must be loopback, and IPv6 must not be?
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.
Got more understanding after reading the design proposal. I think no need to restrict the IP must be link-local. We can recommend link-local though.
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 @jianjuns, updated.
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 mean there are possibilities we don't need to do DNAT in future like the two approaches we have discussed. Even if we still need it for loopback address ( maybe we don't need it for this case as well), I think hardcoding a reserved IP is enough at this stage.
I just want to avoid introducing implementation specific configurations when it's not stable so we don't have the complexity of upgrade (If user set it and we delete it in future, the process will crash).
And it doesn't seem that user can get what the configuration means and how to use it with the current comments.
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.
@tnqn, thanks for the explanation. I removed these two options and made them constant for now.
c0b7207
to
6d0ad1c
Compare
6d21ce5
to
550f9d2
Compare
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 you have a design doc for the reviewers to understand the design?
@@ -116,3 +119,13 @@ featureGates: | |||
# whenever a Pod's container defines a specific port to be exposed (each container can define a list of ports as pod.spec.containers[].ports), | |||
# and all Node traffic directed to that port will be forwarded to the Pod. | |||
#nplPortRange: 40000-41000 | |||
|
|||
# The virtual IP for NodePort Service support. It must be a link-local IP otherwise the Agents will report error. | |||
#nodePortVirtualIP: 169.254.169.110 |
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.
Why we care it must be link-local?
cmd/antrea-agent/agent.go
Outdated
@@ -180,17 +184,27 @@ func run(o *Options) error { | |||
|
|||
var proxier k8sproxy.Provider | |||
if features.DefaultFeatureGate.Enabled(features.AntreaProxy) { | |||
var nodePortAddresses []*net.IPNet |
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 feel we should have a separate feature gate to control NodePort by AntreaProxy or not.
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, I added a new feature gate AntreaProxyNodePort
to control it. Also, I updated the workflow here. The parsing of NodeAddress will go only if both AntreaProxyNodePort
and AntreaProxy
are enabled.
I attached the issue which includes the design. |
Thanks @tnqn. I have fixed this issue and added checks in e2e. |
b2656b1
to
401cbb7
Compare
/test-all |
401cbb7
to
97aacdf
Compare
/test-all |
Windows conformance failed due to infrastructure failure, re-trigger it. |
e8ff683
to
41cbccb
Compare
/test-all |
/jenkins-ipv6-ds-conformance |
I do not mean to ask for a design change for this PR, but have we considered using TC to redirect traffic (https://man7.org/linux/man-pages/man8/tc-mirred.8.html)? Could it be faster or slower than iptables? @tnqn |
/test-all Jenkins tests failed on some unrelated cases, re-trigger tests to have a double-check.
|
/test-ipv6-ds-conformance |
/test-windows-conformance |
@@ -1283,6 +1283,9 @@ data: | |||
# Service traffic. | |||
# AntreaProxy: true | |||
|
|||
# Enable NodePort Service support in AntreaProxy in antrea-agent. | |||
AntreaProxyNodePort: true |
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 would suggest not to enable it by default. Even we enable it, it does not provide any value, until we have a solution to remove kube-proxy.
@tnqn @antoninbas
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.
Agreed
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.
This is the plan. I think Weiqiang only enables it for testing. See PR description "To verify this PR, the NodePort support is enabled. The feature gate should be disabled before merging this 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.
Yes, it is enabled only for testing. I will disable it when we're ready to merge.
41cbccb
to
f0837fa
Compare
df06836
to
533826a
Compare
5b3b1fd
to
2342515
Compare
Resolves antrea-io#1463. Signed-off-by: Weiqiang Tang <[email protected]>
2342515
to
0b6dcd4
Compare
} | ||
|
||
func newOptions() *Options { | ||
return &Options{ | ||
nodePortVirtualIP: net.ParseIP(defaultNodePortVirtualIP), |
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.
Probably better to move these to setDefaults()? I am fine to keep these two options hardcoded for now, but maybe later we should still make them configurable.
@@ -29,50 +29,54 @@ import ( | |||
const NodePortLocalChain = "ANTREA-NODE-PORT-LOCAL" | |||
|
|||
// IPTableRules provides a client to perform IPTABLES operations | |||
type iptablesRules struct { | |||
type IPTableRules struct { |
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 you remove "s" from "iptables" to IPTable" on purpose? I feel it should be "IPTablesRules".
@@ -532,6 +532,15 @@ func (c *client) InstallGatewayFlows() error { | |||
// Add flow to ensure the liveness check packet could be forwarded correctly. | |||
flows = append(flows, c.localProbeFlow(gatewayIPs, cookie.Default)...) | |||
flows = append(flows, c.ctRewriteDstMACFlows(gatewayConfig.MAC, cookie.Default)...) | |||
if c.enableProxy { |
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.
Should we add the flows only when NodePort is enabled?
func (c *client) arpNodePortVirtualResponderFlow() binding.Flow { | ||
return c.pipeline[arpResponderTable].BuildFlow(priorityNormal).MatchProtocol(binding.ProtocolARP). | ||
MatchARPOp(1). | ||
MatchARPTpa(c.nodePortVirtualIPv4). |
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.
When Node IP is v6, no need to add this flow.
@@ -657,3 +794,145 @@ func (c *Client) UnMigrateRoutesFromGw(route *net.IPNet, linkName string) error | |||
} | |||
return nil | |||
} | |||
|
|||
func (c *Client) ReconcileNodePort(nodeIPs []net.IP, svcEntries []*proxytypes.ServiceInfo) error { |
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 did not see this func is called, but might be my mistake?
@@ -38,6 +39,20 @@ type Interface interface { | |||
// It should do nothing if the routes don't exist, without error. | |||
DeleteRoutes(podCIDR *net.IPNet) error | |||
|
|||
// AddRoutes should add the route to the NodePort virtual IP. | |||
AddNodePortRoute(isIPv6 bool) error |
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.
What you think adding a separate interface for AddNodePortRoute, AddNodePort, and DeleteNodePort, which can have different implementations in Linux (by Route Client) and Windows (by Openflow)? Or maybe on Windows they are not needed at all, as the existing Openflow Client interfaces can already cover these functions?
Note: To verify this PR, the NodePort support is enabled. The feature gate should be disabled before merging this PR.
Resolves #1463.
Signed-off-by: Weiqiang Tang [email protected]