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
Use ip address from CNI output #68876
Use ip address from CNI output #68876
Conversation
Before this patch Kubernetes obtains ip address from container's eth device. But in case when containers work only with loopback device and with vhostuser (it's not device it's UNIX domain socket file) Kubernetes can't rely on this approach, it should rely on CNI output. Most of plugins provide IP address of created port. This patch also touches unit test, CNI spec declares ip field as mandatory field of ADD/GET command output. But some users may relay on current behaviour so code where ip is empty and obtained from container's eth is preserved, but it's not covered in unit test. Signed-off-by: Alexey Perevalov <a.perevalov@samsung.com> Fixes kubernetes#65756
@AlexeyPerevalov: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it. 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. |
/assign @dchen1107 |
/assign @dcbw |
/ok-to-test |
/sig network |
return nil, nil | ||
} | ||
|
||
curRes, err := cnicurrent.NewResultFromResult(res) |
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 also log result conversion errors here? Otherwise the pod IP cache will be empty for the pod even though the CNI call succeeded.
curRes, err := cnicurrent.NewResultFromResult(res) | ||
if curRes != nil && len(curRes.IPs) != 0 { | ||
glog.V(4).Infof("IP address for CNI network was set from plugin's output", netConf.Name, netConf.Plugins[0].Network.Type) | ||
plugin.SetPodIPs(podSandboxID, curRes.IPs[0].Address.IP.To4().String()) |
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.
A couple of issues with this block, which is too simple:
- The first IP address in the list might be for any interface, not just the pod's interface. CNI 0.3.0 and later plugins report multiple interfaces and IP addresses, and you need to make sure the IP is actually for the pod interface and not for say the host's bridge interface.
- The code isn't IPv6 compatible due to the To4()
- It should probably warn if the pod interface it finds is not called "eth0", which is what dockershim explicitly requests and which plugins are required to honor by the CNI spec
Instead, something like this:
// Find the pod's IP (ignoring any non-sandbox interfaces)
var podIP string
for _, ip := range curRes.IPs {
if ip.Interface != nil {
if len(curRes.Interfaces) > *ip.Interface {
intf := curRes.Interfaces[*ip.Interface]
if intf.Sandbox != "" && intf.Name == network.DefaultInterfaceName {
// Found our sandbox interface, use the IP
podIP = ip.Address.IP.String()
break
}
}
} else if podIP == "" {
// Fall back to first un-associated address for compatibility
// with older CNI plugins
podIP = ip.Address.IP.String()
}
}
@@ -333,6 +347,22 @@ func (plugin *cniNetworkPlugin) deleteFromNetwork(network *cniNetwork, podName s | |||
return nil | |||
} | |||
|
|||
func (plugin *cniNetworkPlugin) SetPodIPs(podSandboxID kubecontainer.ContainerID, ipAddress string) { |
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 function only sets one pod IP address, so it should probably be SetPodIP() (eg, not plural)
} | ||
} | ||
|
||
func (plugin *cniNetworkPlugin) GetPodIPs(podSandboxID kubecontainer.ContainerID) string { |
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.
Same here, function name probably shouldn't be plural.
@@ -60,6 +61,11 @@ func (plugin *cniNetworkPlugin) platformInit() error { | |||
// TODO: Use the addToNetwork function to obtain the IP of the Pod. That will assume idempotent ADD call to the plugin. | |||
// Also fix the runtime's call to Status function to be done only in the case that the IP is lost, no need to do periodic calls | |||
func (plugin *cniNetworkPlugin) GetPodNetworkStatus(namespace string, name string, id kubecontainer.ContainerID) (*network.PodNetworkStatus, 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.
Should have a comment here about the ordering of how to get the pod's IP address.
But really, we should simply stop jumping into the namespace to check the pod's IP, and just rely on the CNI plugin's result since that result is authoritative. Then we can get rid of the code in docker_sandbox.go in getIP() that checks Docker's NetworkSettings too. Some of the Windows code could also be consolidated perhaps.
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 remove code related to nsenter, because I hope to keep compatibility with CNI plugins which relies on it. But frankly saying I don't know such plugins, I see workarounds in kuryr-kubernetes and intel's vhostuser can work only in couple with multus - it's the same workaround.
So lets remove nsenter code ;)
Do you expect that in separate patch?
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 found, just removing nsenter approach it's not good idea, due to GetPodNetworkStatus is called after kubelet restart, and IP in plugin is empty. I think it's better to store that ip in etcd for that case.
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: AlexeyPerevalov If they are not already assigned, you can assign the PR to them by writing 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 files:
Approvers can indicate their approval by writing |
Before this patch Kubernetes obtained ip address from container's eth device. But in case when containers work only with loopback device and with vhostuser (it's not device it's UNIX domain socket file) Kubernetes can't rely on this approach, it should rely on CNI output. Most of plugins provide IP address of created port. This patch also touches unit test, CNI spec declares ip field as mandatory field of ADD/GET command output. But some users may relay on current behaviour so code where ip is empty and obtained from container's eth is preserved, but it's not covered in unit test. Signed-off-by: Alexey Perevalov <a.perevalov@samsung.com> Fixes kubernetes#65756
@AlexeyPerevalov: The following tests failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. 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. I understand the commands that are listed here. |
/assign @dcbw |
Before this patch Kubernetes obtains ip address from container's eth
device. But in case when containers work only with loopback device and
with vhostuser (it's not device it's UNIX domain socket file) Kubernetes
can't rely on this approach, it should rely on CNI output. Most of plugins
provide IP address of created port.
This patch also touches unit test, CNI spec declares ip field as mandatory
field of ADD/GET command output. But some users may relay on current behaviour
so code where ip is empty and obtained from container's eth is preserved,
but it's not covered in unit test.
Signed-off-by: Alexey Perevalov a.perevalov@samsung.com
Fixes #65756
What this PR does / why we need it:
Which issue(s) this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)
format, will close the issue(s) when PR gets merged):Fixes #
Special notes for your reviewer:
Release note: