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

[Windows] Kube-proxy replacement for NodePort #2863

Merged
merged 1 commit into from
Oct 22, 2021

Conversation

lzhecheng
Copy link
Contributor

No description provided.

@codecov-commenter
Copy link

codecov-commenter commented Oct 4, 2021

Codecov Report

Merging #2863 (5622c95) into main (e81f444) will increase coverage by 0.17%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2863      +/-   ##
==========================================
+ Coverage   60.32%   60.50%   +0.17%     
==========================================
  Files         283      283              
  Lines       23603    23644      +41     
==========================================
+ Hits        14239    14305      +66     
+ Misses       7845     7808      -37     
- Partials     1519     1531      +12     
Flag Coverage Δ
kind-e2e-tests 47.59% <ø> (+0.16%) ⬆️
unit-tests 40.90% <ø> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
pkg/agent/config/node_config.go 100.00% <ø> (ø)
...ver/registry/controlplane/nodestatssummary/rest.go 50.00% <0.00%> (-50.00%) ⬇️
pkg/antctl/antctl.go 66.66% <0.00%> (-33.34%) ⬇️
pkg/controller/networkpolicy/status_controller.go 73.20% <0.00%> (-3.93%) ⬇️
pkg/agent/controller/traceflow/packetin.go 64.60% <0.00%> (-0.37%) ⬇️
pkg/agent/flowexporter/exporter/exporter.go 80.98% <0.00%> (-0.33%) ⬇️
pkg/agent/route/route_linux.go 49.60% <0.00%> (-0.33%) ⬇️
pkg/agent/proxy/proxier.go 60.20% <0.00%> (ø)
pkg/ovs/ovsctl/interface.go 0.00% <0.00%> (ø)
pkg/agent/querier/querier.go 83.75% <0.00%> (ø)
... and 11 more

@lzhecheng lzhecheng force-pushed the win-nodeport-lb branch 4 times, most recently from 0400651 to 6c65f47 Compare October 13, 2021 09:21
@lzhecheng lzhecheng changed the title [WIP][Windows] Kube-proxy replacement for NodePort [Windows] Kube-proxy replacement for NodePort Oct 13, 2021
@lzhecheng lzhecheng requested review from hongliangl, wenyingd, tnqn, jianjuns and antoninbas and removed request for hongliangl and wenyingd October 14, 2021 00:55
@lzhecheng
Copy link
Contributor Author

For the reviewers, please notice that this PR is base on ClusterIP one which still changes from time to time. So just review the last commit is enough. Thank you.
6c65f47

// it cannot be 169.254.1.0 through 169.254.255.255.
// So 169.254.0.253 is a valid one.
ServiceNodePortVirtualIP = net.ParseIP("169.254.0.253").To4()
ServiceNodePortVirtualIPNet = util.NewIPNet(ServiceNodePortVirtualIP)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please provide the referrence link why 169.254.0.253 is valid.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

c.pipeline[serviceClassifierTable].BuildFlow(priorityNormal).
Cookie(c.cookieAllocator.Request(cookie.Service).Raw()).
MatchProtocol(ipProtocol).
MatchDstIP(ServiceNodePortVirtualIP).
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to use ServiceNodePortVirtualIP on Linux, so that we could have a unique flow for both Linux and Window? @hongliangl @lzhecheng

pkg/agent/route/route_windows.go Outdated Show resolved Hide resolved
@lzhecheng lzhecheng force-pushed the win-nodeport-lb branch 2 times, most recently from 5d8db89 to e428019 Compare October 14, 2021 06:44
VirtualServiceIPv4 = net.ParseIP("169.254.169.253")
VirtualServiceIPv6 = net.ParseIP("fc01::aabb:ccdd:eeff")
VirtualServiceIPv4 = net.ParseIP("169.254.169.253")
VirtualServiceIPv4Net = util.NewIPNet(VirtualServiceIPv4)
Copy link
Contributor

Choose a reason for hiding this comment

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

If it is used in route_windows.go only, probably define a local variable there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated in the cluster ip pr.

Copy link
Member

Choose a reason for hiding this comment

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

forgot to update?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Forgot to update after rebasing. It is correct now.

@@ -190,8 +197,30 @@ func (c *Controller) removeStaleGatewayRoutes() error {
desiredPodCIDRs = append(desiredPodCIDRs, podCIDRs...)
}

// TODO: This is not the best place to keep the ClusterIP Service routes.
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, it is strange we reconcile Service routes here. Should we reconcile Service routes from proxier? @hongliangl @tnqn

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we shouldn't use more than one reconcile functions. If so, they may delete the routes added by another function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the current conclusion is that these code is needed for function before a refactor is conducted. Such refactor will be in another PR.

docs/design/windows-design.md Show resolved Hide resolved
@lzhecheng lzhecheng added area/proxy Issues or PRs related to proxy functions in Antrea review-manager-test labels Oct 18, 2021
@lzhecheng lzhecheng force-pushed the win-nodeport-lb branch 4 times, most recently from 3bc578d to c8640e9 Compare October 18, 2021 12:38
vRoute := &util.Route{
LinkIndex: linkIndex,
DestinationSubnet: virtualServiceIPv4Net,
GatewayAddress: net.IPv4zero,
RouteMetric: util.MetricHigh,
RouteMetric: metric,
Copy link
Member

Choose a reason for hiding this comment

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

This change seems pointless.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated. Originally I'd like to have 2 routes here so I defined a variable.

VirtualServiceIPv4 = net.ParseIP("169.254.169.253")
VirtualServiceIPv6 = net.ParseIP("fc01::aabb:ccdd:eeff")
VirtualServiceIPv4 = net.ParseIP("169.254.169.253")
VirtualServiceIPv4Net = util.NewIPNet(VirtualServiceIPv4)
Copy link
Member

Choose a reason for hiding this comment

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

forgot to update?

MatchProtocol(ipProtocol).
MatchDstIP(config.VirtualServiceIPv4).
Action().LoadRegMark(ToNodePortAddressRegMark).
Done())
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this flow duplicated with the above one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.

@@ -36,6 +36,9 @@ import (
const (
inboundFirewallRuleName = "Antrea: accept packets from local Pods"
outboundFirewallRuleName = "Antrea: accept packets to local Pods"

antreaNat = "antrea-nat"
antreaNatStaticMapping = "antrea-natstaticmapping"
Copy link
Member

Choose a reason for hiding this comment

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

Is this nat specific for nodeport traffic? If yes, could we name it in a way that can be associated with NodePort?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, updated.

@@ -377,6 +389,7 @@ func (c *Client) DeleteSNATRule(mark uint32) error {
}

func (c *Client) AddNodePort(nodePortAddresses []net.IP, port uint16, protocol binding.Protocol) error {
util.AddNetNatStaticMapping(antreaNatStaticMapping, "0.0.0.0", port, config.VirtualServiceIPv4, port, string(protocol))
Copy link
Member

Choose a reason for hiding this comment

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

it should handle the error

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

@@ -239,6 +244,13 @@ func (c *Client) addVirtualServiceIPRoute(isIPv6 bool) error {
return err
}
klog.InfoS("Added virtual Service IP neighbor", "neighbor", vNeighbor)

// For NodePort Service, a new NetNat for NetNatStaticMapping is needed.
err := util.NewNetNat(antreaNatStaticMapping, config.VirtualServiceIPv4Net)
Copy link
Member

Choose a reason for hiding this comment

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

VirtualServiceIPv4Net is the original IP or the translation IP?

Copy link
Contributor Author

@lzhecheng lzhecheng Oct 19, 2021

Choose a reason for hiding this comment

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

virtualServiceIPv4Net is the translated: 169.254.0.253/32

Copy link
Member

@tnqn tnqn left a comment

Choose a reason for hiding this comment

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

The code LGTM overall, why don't squash the commits and add the description to the PR description as well?
I think it doesn't respect nodePortAddresses? Is it possible to support it? If yes, we should have an issue to track it. Regardless of whether it's possible, the comment of nodePortAddresses should mention it doesn't work for Windows yet.

@lzhecheng
Copy link
Contributor Author

The code LGTM overall, why don't squash the commits and add the description to the PR description as well? I think it doesn't respect nodePortAddresses? Is it possible to support it? If yes, we should have an issue to track it. Regardless of whether it's possible, the comment of nodePortAddresses should mention it doesn't work for Windows yet.

@tnqn I have squashed the commits and added a TODO for nodePortAddresses. I will create an issue for it later. Besides, I updated NetNatStaticMapping powershell usage.

Copy link
Member

@tnqn tnqn left a comment

Choose a reason for hiding this comment

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

Found two minor problems in the final review

@@ -658,6 +657,67 @@ func CreateNetNatOnHost(subnetCIDR *net.IPNet) error {
return nil
}

func ReplaceNetNatStaticMapping(netNatName string, externalIPAddr string, externalPort uint16, internalIPAddr net.IP, internalPort uint16, proto string) error {
Copy link
Member

Choose a reason for hiding this comment

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

  1. It's strange that externalIPAddr is a string but internalIPAddr is net.IP, can we unify it to string?
  2. The function doesn't really do "replace": replace means it searchs the mapping based on the natName, externalIPAddress, externalPort, protocol, and overrides the mapping if the internalIPAddr, internalPort don't match. In current code, even if there is a mapping that have same external IP and port but different internal IP and port, it's not able to replace it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. Updated.
  2. Now GetNetNatStaticMapping doesn't filter with internal IP and Port. Instead in ReplaceNetNatStaticMapping, it checks if internal IP and Port match inputs.

Copy link
Member

Choose a reason for hiding this comment

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

  1. I don't see it's updated.
  2. It does not make sense to pass internalIPAddr, internalPort to GetNetNatStaticMapping and just ingore them in the body.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. Sorry, some git issue. Now it is correct.
  2. Removed these parameters.

}

// GetNetNatStaticMapping checks if a NetNatStaticMapping exists.
func GetNetNatStaticMapping(netNatName string, externalIPAddr string, externalPort uint16, internalIPAddr net.IP, internalPort uint16, proto string) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

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

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

Copy link
Member

Choose a reason for hiding this comment

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

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated this time.

@@ -658,6 +657,67 @@ func CreateNetNatOnHost(subnetCIDR *net.IPNet) error {
return nil
}

func ReplaceNetNatStaticMapping(netNatName string, externalIPAddr string, externalPort uint16, internalIPAddr net.IP, internalPort uint16, proto string) error {
Copy link
Member

Choose a reason for hiding this comment

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

  1. I don't see it's updated.
  2. It does not make sense to pass internalIPAddr, internalPort to GetNetNatStaticMapping and just ingore them in the body.

}
parsed := parseGetNetCmdResult(staticMappingStr, 6)
if len(parsed) > 1 {
return fmt.Errorf("when ReplaceNetNatStaticMapping, number of parsed result of Get-NetNatStaticMapping is larger than 1, %v", parsed)
Copy link
Member

Choose a reason for hiding this comment

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

I tested get-netnatstaticmapping, it's not possible to install two mapping with same externalIPAddr+externalPort and different internalIPAddr+internalPort, and it makes sense from the API's perspective. So let's don't add code to handle something that won't happen.
It could just handle found case:

if len(parsed) > 0 {
        items := parsed[0]
        ...
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

if err != nil {
return err
}
if err := RemoveNetNatStaticMappingDirect(netNatName, id); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Why Direct? Maybe you mean RemoveNetNatStaticMappingByID?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Originally I'd like to emphasize that it runs Remove-NetNatStaticMapping command directly. But ByID is good. Updated.

}

// GetNetNatStaticMapping checks if a NetNatStaticMapping exists.
func GetNetNatStaticMapping(netNatName string, externalIPAddr string, externalPort uint16, internalIPAddr net.IP, internalPort uint16, proto string) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

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

ditto

return err
}

func RemoveNetNatStaticMapping(netNatName string, externalIPAddr string, externalPort uint16, internalIPAddr string, internalPort uint16, proto string) error {
Copy link
Member

Choose a reason for hiding this comment

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

Similarly, it doesn't make sense to pass internalIPAddr and internalPort but ignore them in the function, which could give people a pression that it will only remove the mapping when all parameters match.

I understand we want to share some code between ReplaceNetNatStaticMapping and RemoveNetNatStaticMapping, then maybe we don't need RemoveNetNatStaticMappingByID and RemoveNetNatStaticMapping could have all arguments. In ReplaceNetNatStaticMapping, it could call RemoveNetNatStaticMapping with the given externalIPAddr and externalPort and the got internalIPAddr and internalPort.

Another approach is to remove internalIPAddr and internalPort from the arguments.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Go with the second approach.

I think only if calling NewNetNatStaticMapping needs internalIPAddr and internalPort soRemoveNetNatStaticMapping just doesn't need it. I am not sure why

In ReplaceNetNatStaticMapping, it could call RemoveNetNatStaticMapping

Since ReplaceNetNatStaticMapping calls RemoveNetNatStaticMapping means calling GetNetNatStaticMapping twice.

Copy link
Member

@tnqn tnqn Oct 20, 2021

Choose a reason for hiding this comment

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

I forgot to mention in the first approach RemoveNetNatStaticMapping should call the command directly without calling GetNetNatStaticMapping first. The function should check if the returned error is "mapping not exist" and ignore it if yes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am bit confused. Without GetNetNatStaticMapping, StaticMappingID is unknown for Remove-NetNatStaticMapping.

Copy link
Member

Choose a reason for hiding this comment

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

I thought Remove-NetNatStaticMapping supports removing it by other arguments like ExternalIPAddress. But it seems not, so 1st approach can't work

tnqn
tnqn previously approved these changes Oct 20, 2021
Copy link
Member

@tnqn tnqn left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@jianjuns jianjuns left a comment

Choose a reason for hiding this comment

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

Just a minor comment.

@@ -52,7 +52,10 @@ var (
// - Use the virtual IP as onlink routing entry gateway in host routing entry.
// - Use the virtual IP as destination IP in host routing entry. It is used to forward DNATed NodePort packets
// or replied SNATed Service packets back to Antrea gateway.
VirtualServiceIPv4 = net.ParseIP("169.254.169.253")
// - Use the virtual IP for InternalIPAddress parameter of Add-NetNatStaticMapping.
// For Antrea, it cannot be an IP used by users but for Add-NetNatStaticMapping it cannot be 169.254.1.0
Copy link
Contributor

Choose a reason for hiding this comment

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

"The IP cannot be one used in the network, and cannot to be within the 169.254.1.0 - 169.254.254.255 range according to IETF."?

Probably remove "So 169.254.0.253 is a valid one"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

Create "antrea-nat-nodeport" NetNat and the NetNatStaticMapping.
Then destination IP of a packet with NodePort will be DNATed to
VirtualServiceIPv4 at the Windows host network.

Signed-off-by: Zhecheng Li <[email protected]>
@lzhecheng
Copy link
Contributor Author

/test-integration

@lzhecheng
Copy link
Contributor Author

/test-all /test-windows-all

@lzhecheng
Copy link
Contributor Author

/test-windows-networkpolicy

@tnqn tnqn merged commit 93170ab into antrea-io:main Oct 22, 2021
@lzhecheng lzhecheng deleted the win-nodeport-lb branch October 22, 2021 02:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/proxy Issues or PRs related to proxy functions in Antrea review-manager-test
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants