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

Add IPv4/v6 dual stack support in Flow aggregator #1962

Merged
merged 1 commit into from
Mar 26, 2021

Conversation

dreamtalen
Copy link
Contributor

@dreamtalen dreamtalen commented Mar 16, 2021

After investigation, we found that the e2e test failure in dual stack cluster of flow aggregator is because we couldn't retrieve the service info from antrea-agent-proxier for IPv6 service address in jenkins dual stack cluster.

In this commit, we fixed a bug in GetServiceByIP() function of dual-stack proxy.
Also, we improved the e2e test of flow aggregator: for dual stack clusters, we will test services for both IPv4 and IPv6 clusterIP.

@dreamtalen
Copy link
Contributor Author

/test-ipv6-only-e2e
/test-ipv6-e2e

@codecov-io
Copy link

codecov-io commented Mar 17, 2021

Codecov Report

Merging #1962 (6b2fe93) into main (2c1666d) will increase coverage by 1.70%.
The diff coverage is 0.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1962      +/-   ##
==========================================
+ Coverage   65.37%   67.08%   +1.70%     
==========================================
  Files         197      197              
  Lines       17217    18014     +797     
==========================================
+ Hits        11256    12085     +829     
+ Misses       4786     4708      -78     
- Partials     1175     1221      +46     
Flag Coverage Δ
e2e-tests 46.30% <0.00%> (?)
kind-e2e-tests 56.51% <0.00%> (+0.06%) ⬆️
unit-tests 41.82% <0.00%> (-0.03%) ⬇️

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

Impacted Files Coverage Δ
pkg/agent/flowexporter/connections/connections.go 79.38% <ø> (ø)
pkg/agent/proxy/proxier.go 66.77% <0.00%> (-1.14%) ⬇️
pkg/agent/openflow/pipeline_other.go 50.00% <0.00%> (-16.67%) ⬇️
pkg/util/ip/ip.go 80.30% <0.00%> (-6.49%) ⬇️
pkg/agent/openflow/client.go 64.33% <0.00%> (-2.86%) ⬇️
pkg/agent/controller/networkpolicy/packetin.go 68.94% <0.00%> (-1.84%) ⬇️
pkg/agent/openflow/network_policy.go 75.97% <0.00%> (+0.14%) ⬆️
pkg/agent/openflow/pipeline.go 73.13% <0.00%> (+0.38%) ⬆️
pkg/ovs/openflow/ofctrl_bridge.go 49.01% <0.00%> (+1.18%) ⬆️
...ntroller/networkpolicy/networkpolicy_controller.go 71.75% <0.00%> (+1.62%) ⬆️
... and 22 more

@dreamtalen dreamtalen force-pushed the local-fa-ds branch 5 times, most recently from b43f752 to 958314b Compare March 19, 2021 18:10
@srikartati
Copy link
Member

/test-all

Is the "Draft status" still intended?

@dreamtalen
Copy link
Contributor Author

/test-all

Is the "Draft status" still intended?

Hi Srikar, yes it's still under development. I found the dual cluster environment on jenkins is different from my local setup, and I'm still debugging on it.

@dreamtalen dreamtalen force-pushed the local-fa-ds branch 2 times, most recently from 0cde7a5 to 543e90a Compare March 22, 2021 22:26
@dreamtalen
Copy link
Contributor Author

/test-ipv6-only-e2e
/test-ipv6-e2e

@dreamtalen
Copy link
Contributor Author

/test-all
/test-ipv6-only-e2e
/test-ipv6-e2e

@dreamtalen dreamtalen marked this pull request as ready for review March 22, 2021 23:34
@dreamtalen dreamtalen marked this pull request as draft March 23, 2021 17:00
@dreamtalen dreamtalen force-pushed the local-fa-ds branch 2 times, most recently from 9df5a8c to d92cc41 Compare March 23, 2021 18:21
@dreamtalen
Copy link
Contributor Author

/test-all
/test-ipv6-only-e2e
/test-ipv6-e2e

@dreamtalen dreamtalen marked this pull request as ready for review March 23, 2021 21:03
Comment on lines -71 to -75
func skipIfDualStackCluster(tb testing.TB) {
if clusterInfo.podV6NetworkCIDR != "" && clusterInfo.podV4NetworkCIDR != "" {
tb.Skipf("Skipping test as it is not supported in dual stack cluster")
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Keep it for future use?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

}
}

func createSvcRunTests(t *testing.T, data *TestData, podAIP *PodIPs, podBIP *PodIPs, podCIP *PodIPs, isIPv6 bool) {
Copy link
Member

Choose a reason for hiding this comment

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

Separate out createServices function and runTests function for better readability

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

@@ -160,12 +161,12 @@ func (proxier *metaProxier) OnEndpointsSynced() {
}

func (proxier *metaProxier) GetServiceByIP(serviceStr string) (ServicePortName, bool) {
if utilnet.IsIPv6String(serviceStr) {
// Format of serviceStr is fmt.Sprintf("%s:%d/%s", clusterIP, svcPort, protocol), so IPv6 serviceStr has more than 3 colons.
if strings.Count(serviceStr, ":") >= 3 {
Copy link
Member

Choose a reason for hiding this comment

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

Check looks somewhat arbitrary. Can we parse the string with last colon as the separator and use the IP?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

@@ -160,12 +161,12 @@ func (proxier *metaProxier) OnEndpointsSynced() {
}

func (proxier *metaProxier) GetServiceByIP(serviceStr string) (ServicePortName, bool) {
Copy link
Member

Choose a reason for hiding this comment

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

Hi @jianjuns ,
GetServiceByIP is a method in Proxier interface defined in pkg/third_party/proxy
This was originally defined in pkg/agent/proxy but moved to third-party pkg. This is currently used by Flow Exporter running in Agent and no one else uses it.
Therefore, I think it should follow the placement of GetServiceFlowKeys method and placed in pkg/agent/proxy. Do you agree?

Copy link
Contributor

Choose a reason for hiding this comment

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

That sounds good to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks Srikar and Jianjun, moved the GetServiceByIP under pkg/agent/proxy and removed it from Provider interface in third_party/proxy.

@dreamtalen dreamtalen force-pushed the local-fa-ds branch 2 times, most recently from 9a6fa10 to 6901b39 Compare March 24, 2021 00:52
Copy link
Member

@srikartati srikartati left a comment

Choose a reason for hiding this comment

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

Will there be any changes on Kibana dashboard for dual-stack clusters?

pkg/agent/proxy/proxier.go Show resolved Hide resolved
@dreamtalen
Copy link
Contributor Author

Will there be any changes on Kibana dashboard for dual-stack clusters?

Hi Srikar, Kibana dashboard has supported dual stack environment in the previous IPv6 support PR.

@srikartati
Copy link
Member

/test-all
/test-ipv6-e2e
/test-ipv6-only-e2e

srikartati
srikartati previously approved these changes Mar 24, 2021
Copy link
Member

@srikartati srikartati left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -53,6 +54,9 @@ type Proxier interface {
// flows and the OVS group IDs for a Service. False is returned if the
// Service is not found.
GetServiceFlowKeys(serviceName, namespace string) ([]string, []binding.GroupIDType, bool)
// GetServiceByIP returns the ServicePortName struct of giving serviceString(ClusterIP:Port/Proto).
Copy link
Contributor

Choose a reason for hiding this comment

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

"of giving"? do you mean "for the given"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

@@ -53,6 +54,9 @@ type Proxier interface {
// flows and the OVS group IDs for a Service. False is returned if the
// Service is not found.
GetServiceFlowKeys(serviceName, namespace string) ([]string, []binding.GroupIDType, bool)
// GetServiceByIP returns the ServicePortName struct of giving serviceString(ClusterIP:Port/Proto).
// False is returned if the serviceString is not existed in serviceStringMap.
Copy link
Contributor

Choose a reason for hiding this comment

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

s/is not existed/does not exist
or
s/is not existed/is not found

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

@@ -639,6 +643,16 @@ func (p *metaProxierWrapper) GetServiceFlowKeys(serviceName, namespace string) (
return append(v4Flows, v6Flows...), append(v4Groups, v6Groups...), v4Found || v6Found
}

func (p *metaProxierWrapper) GetServiceByIP(serviceStr string) (k8sproxy.ServicePortName, bool) {
// Format of serviceStr is fmt.Sprintf("%s:%d/%s", clusterIP, svcPort, protocol).
Copy link
Contributor

Choose a reason for hiding this comment

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

that's a weird way of presenting it, why not:

// Format of serviceStr is <clusterIP>:<svcPort>/<protocol>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

time.Sleep(3 * time.Second)

runTests(t, data, podAIP, podBIP, podCIP, svcB, svcC, false)
deletePerftestServices(data)
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe use a defer statement after the call to createPerftestServices

same below

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

Comment on lines 129 to 123
if v6Enabled {
svcB, svcC, err := createPerftestServices(data, true)
if err != nil {
t.Fatalf("Error when creating IPv6 perftest services: %v", err)
}
// Wait for the Service to be realized.
time.Sleep(3 * time.Second)

runTests(t, data, podAIP, podBIP, podCIP, svcB, svcC, true)
deletePerftestServices(data)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like the exact same code as above. Maybe define a local function.

testHelper := func(isIPv6 bool) { ... }
if v4Enabled {
    t.Logf("Running tests with IPv4 perftest service")
    testHelper()
}
if v6Enabled
    t.Logf("Running tests with IPv6 perftest service")
    testHelper()
}

or even better, use subtests:

testHelper := func(t *testing.T, isIPv6 bool) { ... }
if v4Enabled {
    t.Run("IPv4", func(t *testing.T) { testHelper(t, false) })
}
if v4Enabled {
    t.Run("IPv6", func(t *testing.T) { testHelper(t, true) })
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed it using subtests.

}
}

func runTests(t *testing.T, data *TestData, podAIP *PodIPs, podBIP *PodIPs, podCIP *PodIPs, svcB *corev1.Service, svcC *corev1.Service, isIPv6 bool) {
Copy link
Contributor

Choose a reason for hiding this comment

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

why is this helper method not in charge of creating the test resources (pods, services)? Why the need to pass them as parameters?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi Antonin, after changing to use subtests, only pod IPs are passed as parameters to the testHelper method. The reason is that we would like to reuse perf pods in both IPv4 and IPv6 tests, while perf services need to be created for IPv4 and IPv6 differently.

Comment on lines 35 to 36
- Add Run(), GetServiceByIP() to Provider interface
- Remove GetServiceByIP() from Provider interface
Copy link
Contributor

Choose a reason for hiding this comment

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

These list the changes compared to upstream...
you should edit the existing last bullet point, not add a new 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.

Thanks, addressed.

Copy link
Contributor

@antoninbas antoninbas left a comment

Choose a reason for hiding this comment

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

some nits, otherwise LGTM

if err != nil {
t.Fatalf("Error when setting up test: %v", err)
}
defer teardownTest(t, data)
defer teardownFlowAggregator(t, data)

podAIP, podBIP, podCIP, svcB, svcC, err := createPerftestPods(data, isIPv6)
podAIP, podBIP, podCIP, err := createPerftestPods(data)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: looks like these should be named podAIPs, podBIPs, podCIPs to match the rest of the code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

if err != nil {
t.Fatalf("Error when creating perftest pods and services: %v", err)
t.Fatalf("Error when creating perftest pods: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

s/pods/Pods

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

func testHelper(t *testing.T, data *TestData, podAIP *PodIPs, podBIP *PodIPs, podCIP *PodIPs, isIPv6 bool) {
svcB, svcC, err := createPerftestServices(data, isIPv6)
if err != nil {
t.Fatalf("Error when creating perftest services: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

s/services/Services

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

if err != nil {
t.Fatalf("Error when creating perftest services: %v", err)
}
defer deletePerftestServices(data)
Copy link
Contributor

Choose a reason for hiding this comment

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

don't you want to log the error if there is 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.

Thanks, addressed.

}
podBIP, err = data.podWaitForIPs(defaultTimeout, "perftest-b", testNamespace)
if err != nil {
return nil, nil, nil, fmt.Errorf("Error when getting the perftest server Pod's IP: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

s/IP/IPs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

if err != nil {
return nil, nil, nil, nil, nil, fmt.Errorf("Error when getting the perftest server Pod's IP: %v", err)
return nil, nil, fmt.Errorf("Error when creating perftest service: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

s/service/Service

same in every other place

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

if err != nil {
return nil, nil, nil, nil, nil, fmt.Errorf("Error when creating perftest service: %v", err)
return nil, nil, nil, fmt.Errorf("Error when getting the perftest server Pod's IP: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

s/IP/IPs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, addressed.

Fixed a bug in GetServiceByIP() function of dual-stack proxy and moved
it under pkg/agent/proxy.
Improved the e2e test of flow aggregator: for dual stack clusters, we
will test services for both IPv4 and IPv6 clusterIP.
Copy link
Contributor

@antoninbas antoninbas left a comment

Choose a reason for hiding this comment

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

LGTM

@srikartati
Copy link
Member

/test-all

@srikartati
Copy link
Member

/test-e2e
/test-ipv6-e2e
/test-ipv6-only-e2e

@dreamtalen
Copy link
Contributor Author

/test-ipv6-e2e
/test-ipv6-only-e2e

@srikartati
Copy link
Member

All the reviews are done. Merging this.

@srikartati srikartati merged commit ae0705a into antrea-io:main Mar 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants