Merge pull request #54052 from m1093782566/netlink

Automatic merge from submit-queue (batch tested with PRs 55247, 55324, 55261, 55147, 54052). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Implement dummy device operation by netlink for ipvs proxier

**What this PR does / why we need it**:

Currently, we implement network interface operations, e.g. create a dummy device and delete a dummy interface via ip cmd and then collect the exist code. For example, we assume the following command:
```
ip link add kube-ipvs0 type dummy 
```
returns 2 means the dummy device `kube-ipvs0` exists, see https://github.com/kubernetes/kubernetes/blob/master/pkg/proxy/ipvs/proxier.go#L1529 .

However, from the man page of ip command, exit status 2 just means an error was reported by the kernel, see http://man7.org/linux/man-pages/man8/ip.8.html#EXIT_STATUS.

So, that's a bug.

This PR implements dummy device operation by netlink for ipvs proxier so that can get ride of ip command operations.

**Which issue this PR fixes**: 

fixes #54054

**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```

/sig network
/area kube-proxy
/kind bug
This commit is contained in:
Kubernetes Submit Queue
2017-11-09 00:59:32 -08:00
committed by GitHub
9 changed files with 60 additions and 105 deletions

View File

@@ -748,7 +748,7 @@ func cleanupIptablesLeftovers(ipt utiliptables.Interface) (encounteredError bool
}
// CleanupLeftovers clean up all ipvs and iptables rules created by ipvs Proxier.
func CleanupLeftovers(execer utilexec.Interface, ipvs utilipvs.Interface, ipt utiliptables.Interface) (encounteredError bool) {
func CleanupLeftovers(ipvs utilipvs.Interface, ipt utiliptables.Interface) (encounteredError bool) {
// Return immediately when ipvs interface is nil - Probably initialization failed in somewhere.
if ipvs == nil {
return true
@@ -761,7 +761,8 @@ func CleanupLeftovers(execer utilexec.Interface, ipvs utilipvs.Interface, ipt ut
encounteredError = true
}
// Delete dummy interface created by ipvs Proxier.
err = deleteDummyDevice(execer, DefaultDummyDevice)
nl := NewNetLinkHandle()
err = nl.DeleteDummyDevice(DefaultDummyDevice)
if err != nil {
encounteredError = true
}
@@ -950,7 +951,7 @@ func (proxier *Proxier) syncProxyRules() {
// End install iptables
// make sure dummy interface exists in the system where ipvs Proxier will bind service address on it
_, err = ensureDummyDevice(proxier.exec, DefaultDummyDevice)
_, err = proxier.netlinkHandle.EnsureDummyDevice(DefaultDummyDevice)
if err != nil {
glog.Errorf("Failed to create dummy interface: %s, error: %v", DefaultDummyDevice, err)
return
@@ -1525,32 +1526,6 @@ func openLocalPort(lp *utilproxy.LocalPort) (utilproxy.Closeable, error) {
return socket, nil
}
const cmdIP = "ip"
func ensureDummyDevice(execer utilexec.Interface, dummyDev string) (exist bool, err error) {
args := []string{"link", "add", dummyDev, "type", "dummy"}
out, err := execer.Command(cmdIP, args...).CombinedOutput()
if err != nil {
// "exit status code 2" will be returned if the device already exists
if ee, ok := err.(utilexec.ExitError); ok {
if ee.Exited() && ee.ExitStatus() == 2 {
return true, nil
}
}
return false, fmt.Errorf("error creating dummy interface %q: %v: %s", dummyDev, err, out)
}
return false, nil
}
func deleteDummyDevice(execer utilexec.Interface, dummyDev string) error {
args := []string{"link", "del", dummyDev}
out, err := execer.Command(cmdIP, args...).CombinedOutput()
if err != nil {
return fmt.Errorf("error deleting dummy interface %q: %v: %s", dummyDev, err, out)
}
return nil
}
// ipvs Proxier fall back on iptables when it needs to do SNAT for engress packets
// It will only operate iptables *nat table.
// Create and link the kube postrouting chain for SNAT packets.