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

Detect CIDR IPv4 or IPv6 version to select nexthop #59749

Merged
merged 1 commit into from Feb 14, 2018

Conversation

zioproto
Copy link
Member

@zioproto zioproto commented Feb 12, 2018

What this PR does / why we need it:

The node InternalIP is used as nexthop by the Kubernetes master to create routes in the Neutron router for Pods reachability.
If a node has more than one InternalIPs, eventually IPv4 and IPv6, a random InternalIP from the list is returned.
This can lead to the bug described in #59421
We need to check when we build a route that the CIDR and the nexthop belong to the same IP Address Family (both IPv4 or both IPv6)

Which issue(s) this PR fixes :
Fixes #59421
It is related to #55202

Special notes for your reviewer:
This is the suggested way to fix the problem after the discussion in #59502

old release note: Issue #59421 was closed: the Openstack deployment with dual stack (IPv4 and IPv6) nodes and network-plugin=kubenet is now working properly.

Release note:

Fixing a bug in OpenStack cloud provider, where dual stack deployments (IPv4 and IPv6) did not work well when using kubenet as the network plugin.

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Feb 12, 2018
@k8s-ci-robot k8s-ci-robot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Feb 12, 2018
zioproto pushed a commit to zioproto/k8s-on-openstack that referenced this pull request Feb 12, 2018
Copy link
Contributor

@FengyunPan2 FengyunPan2 left a comment

Choose a reason for hiding this comment

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

Sounds good, can we keep getAddressByName()?
Or use a small method since we are using the same thing 2 times, maybe use it at other function later.

@zioproto
Copy link
Member Author

zioproto commented Feb 12, 2018

@FengyunPan2 is it okay then if I pass route.DestinationCIDR as an argument to getAddressByName in order to compute in the function if I should get an IPv4 or IPv6 result ?

@k8s-ci-robot k8s-ci-robot added size/S Denotes a PR that changes 10-29 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Feb 12, 2018
@zioproto
Copy link
Member Author

@FengyunPan2 I pushed a new amended commit. Now the implementation uses the function and there is not code duplication.

@@ -520,12 +521,12 @@ func getAddressByName(client *gophercloud.ServiceClient, name types.NodeName) (s
}

for _, addr := range addrs {
if addr.Type == v1.NodeInternalIP {
if (addr.Type == v1.NodeInternalIP) && (govalidator.IsIPv6(addr.Address) == needIPv6) {

Choose a reason for hiding this comment

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

Might be better to use the more generic 'net' package (instead of asaskevich/govalidator) to determine whether the address is IPv6, e.g.:

isIPv6 := net.ParseIP(addr.Address).To4() == nil
if addr.Type == v1.NodeInternalIP && isIPv6 == needIPv6 {
    return addr.Address, nil
}

Copy link
Member Author

Choose a reason for hiding this comment

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

hello @leblancd
I checked https://stackoverflow.com/questions/22751035/golang-distinguish-ipv4-ipv6

Please check in particular this answer: https://stackoverflow.com/a/48519490/1506396
It is the exaplanation why to use govalidator instead of the net package.

Choose a reason for hiding this comment

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

Hi @zioproto:
I would respectfully disagree with what the poster is claiming in this stackoverflow answer. Specifically, the list of addresses that are labeled "Valid IPv6 notations" should be labeled instead "IPv4-mapped IPv6 Notations" (RFC4291 and RFC4038). These addresses have an IPv6 format, but are intended to be internal representations of IPv4 addresses on the wire. They're essentially IPv4 addresses encapsulated in an IPv6 frame, and this is done so that dual-stack software can conveniently handle both IPv4 and IPv6 addresses as 16-byte entities. The net package's To4() takes care to look for this pattern in a 16-byte slice, and (correctly, I believe) creates an 4-byte (IPv4) slice from the lowest 4 bytes (since Golang can handle slices of arbitrary length, so there's no need to perpetuate the 16-byte internal representation of IPv4-mapped IPv6 addresses). In the examples given in the post, the only addresses that the net's To4() gets wrong, in my opinion, are the examples with :port appended, but To4() assumes that the caller has taken care of eliminating any :port (e.g. with splitHostPort()).

@@ -146,7 +148,10 @@ func (r *Routes) CreateRoute(ctx context.Context, clusterName string, nameHint s

onFailure := newCaller()

addr, err := getAddressByName(r.compute, route.TargetNode)
IP, _, _ := net.ParseCIDR(route.DestinationCIDR)
CIDRisV6 := govalidator.IsIPv6(IP.String())

Choose a reason for hiding this comment

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

Same comment as before, can use 'net' package to test for IPv6, e.g.:

CIDRisV6 := IP.To4() == nil

@dims
Copy link
Member

dims commented Feb 12, 2018

/ok-to-test

@k8s-ci-robot k8s-ci-robot removed the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Feb 12, 2018
@leblancd
Copy link

leblancd commented Feb 12, 2018

Looks good to me. Thanks, @zioproto for taking care of this!

@leblancd
Copy link

/test pull-kubernetes-bazel-test

@FengyunPan2
Copy link
Contributor

@zioproto Yeah, nice work.
/lgtm

@k8s-ci-robot
Copy link
Contributor

@FengyunPan2: changing LGTM is restricted to assignees, and only kubernetes org members may be assigned issues.

In response to this:

@zioproto Yeah, nice work.
/lgtm

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@dims
Copy link
Member

dims commented Feb 13, 2018

/approve
/lgtm

@k8s-ci-robot k8s-ci-robot added lgtm "Looks good to me", indicates that a PR is ready to be merged. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Feb 13, 2018
return addr.Address, nil
}
}

return addrs[0].Address, nil
return "", ErrNoAddressFound
Copy link
Member

Choose a reason for hiding this comment

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

With this last change, this function will only return InternalIPs. It should instead try ExternalIPs before giving up.

Aside: An alternate version might be to pass an address family down to getAddressesByName and thence nodeAddresses (with some value to indicate "all" families) and then do the filtering at the lowest level, when we know the address family from the openstack data structure. Happy to go with whatever version you think is best.

@@ -146,7 +147,10 @@ func (r *Routes) CreateRoute(ctx context.Context, clusterName string, nameHint s

onFailure := newCaller()

addr, err := getAddressByName(r.compute, route.TargetNode)
IP, _, _ := net.ParseCIDR(route.DestinationCIDR)
CIDRisV6 := IP.To4() == nil
Copy link
Member

Choose a reason for hiding this comment

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

Both IP and CIDRisV6 should have (at least) a lowercased first letter, to conform with golang's public/private styleguide/rules.

@@ -219,7 +223,10 @@ func (r *Routes) DeleteRoute(ctx context.Context, clusterName string, route *clo

onFailure := newCaller()

addr, err := getAddressByName(r.compute, route.TargetNode)
IP, _, _ := net.ParseCIDR(route.DestinationCIDR)
CIDRisV6 := IP.To4() == nil
Copy link
Member

Choose a reason for hiding this comment

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

Ditto lowercased first letter of local variable.

@dims
Copy link
Member

dims commented Feb 13, 2018

/hold

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Feb 13, 2018
@dims
Copy link
Member

dims commented Feb 13, 2018

/lgtm cancel

@zioproto
Copy link
Member Author

zioproto commented Feb 13, 2018

/test pull-kubernetes-unit

@dims
Copy link
Member

dims commented Feb 13, 2018

/hold cancel

@anguslees please take another look

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Feb 13, 2018
@dims
Copy link
Member

dims commented Feb 13, 2018

/lgtm

@k8s-ci-robot k8s-ci-robot added lgtm "Looks good to me", indicates that a PR is ready to be merged. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Feb 13, 2018
@dims
Copy link
Member

dims commented Feb 13, 2018

/lgtm cancel

@k8s-ci-robot k8s-ci-robot removed lgtm "Looks good to me", indicates that a PR is ready to be merged. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Feb 13, 2018
@dims
Copy link
Member

dims commented Feb 13, 2018

weird, i wanted to indicate lgtm without approving ... bot applied both! never ming. just waiting for @anguslees :)

Copy link
Member

@anguslees anguslees left a comment

Choose a reason for hiding this comment

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

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Feb 14, 2018
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: anguslees, FengyunPan2, zioproto

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these OWNERS Files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 14, 2018
@k8s-github-robot
Copy link

/test all [submit-queue is verifying that this PR is safe to merge]

@fejta-bot
Copy link

/retest
This bot automatically retries jobs that failed/flaked on approved PRs (send feedback to fejta).

Review the full test history for this PR.

Silence the bot with an /lgtm cancel comment for consistent failures.

@zioproto
Copy link
Member Author

/test pull-kubernetes-e2e-kops-aws

@k8s-github-robot
Copy link

/test all [submit-queue is verifying that this PR is safe to merge]

@zioproto
Copy link
Member Author

/test pull-kubernetes-unit

@k8s-github-robot
Copy link

/test all [submit-queue is verifying that this PR is safe to merge]

@k8s-github-robot
Copy link

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here.

@k8s-github-robot k8s-github-robot merged commit 0dda5c8 into kubernetes:master Feb 14, 2018
@zioproto
Copy link
Member Author

/cherrypick-candidate

@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed release-note-none Denotes a PR that doesn't merit a release note. labels Feb 14, 2018
k8s-github-robot pushed a commit that referenced this pull request Feb 25, 2018
…pstream-release-1.9

Automatic merge from submit-queue.

Automated cherry pick of #59749: Detect CIDR IPv4 or IPv6 version to select nexthop

Cherry pick of #59749 on release-1.9.

#59749: Detect CIDR IPv4 or IPv6 version to select nexthop

```release-note
Fixing a bug in OpenStack cloud provider, where dual stack deployments (IPv4 and IPv6) did not work well when using kubenet as the network plugin.
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/S Denotes a PR that changes 10-29 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Openstack Cloud provider mixes IPv4 subnets and IPv6 nexthops in Neutron routes
8 participants