mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 09:22:44 +00:00
move to libcni 0.7.0
Previous commit "Use ip address from CNI output" introduces ability to run pod which can havn't eth0. But also it add problem: after kubelet restart, if we have already started pod w/o eth0, kubelet can't find proper interface (it's normal for vhostuser type of cni plugin when eth0 doesn't exist) and kubelet restarts "broken" pod. Fix of this issue requeres new feature of libcni - caching results. Looks like new libcni requires cniVersion in CNI output. This patch specifies version both for CNI conf and CNI output. Signed-off-by: Alexey Perevalov <a.perevalov@samsung.com>
This commit is contained in:
parent
0e48ec31f3
commit
a2ea2996f3
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package cni
|
package cni
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -326,7 +327,7 @@ func (plugin *cniNetworkPlugin) addToNetwork(network *cniNetwork, podName string
|
|||||||
pdesc := podDesc(podNamespace, podName, podSandboxID)
|
pdesc := podDesc(podNamespace, podName, podSandboxID)
|
||||||
netConf, cniNet := network.NetworkConfig, network.CNIConfig
|
netConf, cniNet := network.NetworkConfig, network.CNIConfig
|
||||||
klog.V(4).Infof("Adding %s to network %s/%s netns %q", pdesc, netConf.Plugins[0].Network.Type, netConf.Name, podNetnsPath)
|
klog.V(4).Infof("Adding %s to network %s/%s netns %q", pdesc, netConf.Plugins[0].Network.Type, netConf.Name, podNetnsPath)
|
||||||
res, err := cniNet.AddNetworkList(netConf, rt)
|
res, err := cniNet.AddNetworkList(context.TODO(), netConf, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Error adding %s to network %s/%s: %v", pdesc, netConf.Plugins[0].Network.Type, netConf.Name, err)
|
klog.Errorf("Error adding %s to network %s/%s: %v", pdesc, netConf.Plugins[0].Network.Type, netConf.Name, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -345,7 +346,7 @@ func (plugin *cniNetworkPlugin) deleteFromNetwork(network *cniNetwork, podName s
|
|||||||
pdesc := podDesc(podNamespace, podName, podSandboxID)
|
pdesc := podDesc(podNamespace, podName, podSandboxID)
|
||||||
netConf, cniNet := network.NetworkConfig, network.CNIConfig
|
netConf, cniNet := network.NetworkConfig, network.CNIConfig
|
||||||
klog.V(4).Infof("Deleting %s from network %s/%s netns %q", pdesc, netConf.Plugins[0].Network.Type, netConf.Name, podNetnsPath)
|
klog.V(4).Infof("Deleting %s from network %s/%s netns %q", pdesc, netConf.Plugins[0].Network.Type, netConf.Name, podNetnsPath)
|
||||||
err = cniNet.DelNetworkList(netConf, rt)
|
err = cniNet.DelNetworkList(context.TODO(), netConf, rt)
|
||||||
// The pod may not get deleted successfully at the first time.
|
// The pod may not get deleted successfully at the first time.
|
||||||
// Ignore "no such file or directory" error in case the network has already been deleted in previous attempts.
|
// Ignore "no such file or directory" error in case the network has already been deleted in previous attempts.
|
||||||
if err != nil && !strings.Contains(err.Error(), "no such file or directory") {
|
if err != nil && !strings.Contains(err.Error(), "no such file or directory") {
|
||||||
|
@ -20,6 +20,7 @@ package cni
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -48,7 +49,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Returns .in file path, .out file path, and .env file path
|
// Returns .in file path, .out file path, and .env file path
|
||||||
func installPluginUnderTest(t *testing.T, testBinDir, testConfDir, testDataDir, binName string, confName string) (string, string, string) {
|
func installPluginUnderTest(t *testing.T, testBinDir, testConfDir, testDataDir, binName string, confName, podIP string) (string, string, string) {
|
||||||
for _, dir := range []string{testBinDir, testConfDir, testDataDir} {
|
for _, dir := range []string{testBinDir, testConfDir, testDataDir} {
|
||||||
err := os.MkdirAll(dir, 0777)
|
err := os.MkdirAll(dir, 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -56,12 +57,14 @@ func installPluginUnderTest(t *testing.T, testBinDir, testConfDir, testDataDir,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cniVersion = "0.2.0"
|
||||||
|
|
||||||
confFile := path.Join(testConfDir, confName+".conf")
|
confFile := path.Join(testConfDir, confName+".conf")
|
||||||
f, err := os.Create(confFile)
|
f, err := os.Create(confFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to install plugin %s: %v", confFile, err)
|
t.Fatalf("Failed to install plugin %s: %v", confFile, err)
|
||||||
}
|
}
|
||||||
networkConfig := fmt.Sprintf(`{ "name": "%s", "type": "%s", "capabilities": {"portMappings": true, "bandwidth": true, "ipRanges": true} }`, confName, binName)
|
networkConfig := fmt.Sprintf(`{ "cniVersion": "%s", "name": "%s", "type": "%s", "capabilities": {"portMappings": true, "bandwidth": true, "ipRanges": true} }`, cniVersion, confName, binName)
|
||||||
_, err = f.WriteString(networkConfig)
|
_, err = f.WriteString(networkConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to write network config file (%v)", err)
|
t.Fatalf("Failed to write network config file (%v)", err)
|
||||||
@ -78,8 +81,8 @@ echo "%@" >> {{.OutputEnv}}
|
|||||||
export $(echo ${CNI_ARGS} | sed 's/;/ /g') &> /dev/null
|
export $(echo ${CNI_ARGS} | sed 's/;/ /g') &> /dev/null
|
||||||
mkdir -p {{.OutputDir}} &> /dev/null
|
mkdir -p {{.OutputDir}} &> /dev/null
|
||||||
echo -n "$CNI_COMMAND $CNI_NETNS $K8S_POD_NAMESPACE $K8S_POD_NAME $K8S_POD_INFRA_CONTAINER_ID" >& {{.OutputFile}}
|
echo -n "$CNI_COMMAND $CNI_NETNS $K8S_POD_NAMESPACE $K8S_POD_NAME $K8S_POD_INFRA_CONTAINER_ID" >& {{.OutputFile}}
|
||||||
echo -n "{ \"ip4\": { \"ip\": \"10.1.0.23/24\" } }"
|
echo -n "{ \"cniVersion\": \"{{.CNIVersion}}\", \"ip4\": { \"ip\": \"{{.PodIP}}/24\" } }"`
|
||||||
`
|
|
||||||
inputFile := path.Join(testDataDir, binName+".in")
|
inputFile := path.Join(testDataDir, binName+".in")
|
||||||
outputFile := path.Join(testDataDir, binName+".out")
|
outputFile := path.Join(testDataDir, binName+".out")
|
||||||
envFile := path.Join(testDataDir, binName+".env")
|
envFile := path.Join(testDataDir, binName+".env")
|
||||||
@ -88,6 +91,8 @@ echo -n "{ \"ip4\": { \"ip\": \"10.1.0.23/24\" } }"
|
|||||||
"OutputFile": outputFile,
|
"OutputFile": outputFile,
|
||||||
"OutputEnv": envFile,
|
"OutputEnv": envFile,
|
||||||
"OutputDir": testDataDir,
|
"OutputDir": testDataDir,
|
||||||
|
"CNIVersion": cniVersion,
|
||||||
|
"PodIP": podIP,
|
||||||
}
|
}
|
||||||
|
|
||||||
tObj := template.Must(template.New("test").Parse(execScriptTempl))
|
tObj := template.Must(template.New("test").Parse(execScriptTempl))
|
||||||
@ -190,7 +195,7 @@ func TestCNIPlugin(t *testing.T) {
|
|||||||
testBinDir := path.Join(tmpDir, "opt", "cni", "bin")
|
testBinDir := path.Join(tmpDir, "opt", "cni", "bin")
|
||||||
testDataDir := path.Join(tmpDir, "output")
|
testDataDir := path.Join(tmpDir, "output")
|
||||||
defer tearDownPlugin(tmpDir)
|
defer tearDownPlugin(tmpDir)
|
||||||
inputFile, outputFile, outputEnv := installPluginUnderTest(t, testBinDir, testConfDir, testDataDir, binName, netName)
|
inputFile, outputFile, outputEnv := installPluginUnderTest(t, testBinDir, testConfDir, testDataDir, binName, netName, podIP)
|
||||||
|
|
||||||
containerID := kubecontainer.ContainerID{Type: "test", ID: "test_infra_container"}
|
containerID := kubecontainer.ContainerID{Type: "test", ID: "test_infra_container"}
|
||||||
pods := []*containertest.FakePod{{
|
pods := []*containertest.FakePod{{
|
||||||
@ -217,7 +222,7 @@ func TestCNIPlugin(t *testing.T) {
|
|||||||
cniPlugin.execer = fexec
|
cniPlugin.execer = fexec
|
||||||
cniPlugin.loNetwork.CNIConfig = mockLoCNI
|
cniPlugin.loNetwork.CNIConfig = mockLoCNI
|
||||||
|
|
||||||
mockLoCNI.On("AddNetworkList", cniPlugin.loNetwork.NetworkConfig, mock.AnythingOfType("*libcni.RuntimeConf")).Return(&types020.Result{IP4: &types020.IPConfig{IP: net.IPNet{IP: []byte{127, 0, 0, 1}}}}, nil)
|
mockLoCNI.On("AddNetworkList", context.TODO(), cniPlugin.loNetwork.NetworkConfig, mock.AnythingOfType("*libcni.RuntimeConf")).Return(&types020.Result{IP4: &types020.IPConfig{IP: net.IPNet{IP: []byte{127, 0, 0, 1}}}}, nil)
|
||||||
|
|
||||||
// Check that status returns an error
|
// Check that status returns an error
|
||||||
if err := cniPlugin.Status(); err == nil {
|
if err := cniPlugin.Status(); err == nil {
|
||||||
|
@ -19,6 +19,7 @@ limitations under the License.
|
|||||||
package mock_cni
|
package mock_cni
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/containernetworking/cni/libcni"
|
"github.com/containernetworking/cni/libcni"
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
@ -28,22 +29,52 @@ type MockCNI struct {
|
|||||||
mock.Mock
|
mock.Mock
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockCNI) AddNetwork(net *libcni.NetworkConfig, rt *libcni.RuntimeConf) (types.Result, error) {
|
func (m *MockCNI) AddNetwork(ctx context.Context, net *libcni.NetworkConfig, rt *libcni.RuntimeConf) (types.Result, error) {
|
||||||
|
args := m.Called(ctx, net, rt)
|
||||||
|
return args.Get(0).(types.Result), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockCNI) DelNetwork(ctx context.Context, net *libcni.NetworkConfig, rt *libcni.RuntimeConf) error {
|
||||||
|
args := m.Called(ctx, net, rt)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockCNI) DelNetworkList(ctx context.Context, net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) error {
|
||||||
|
args := m.Called(ctx, net, rt)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockCNI) GetNetworkListCachedResult(net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) (types.Result, error) {
|
||||||
args := m.Called(net, rt)
|
args := m.Called(net, rt)
|
||||||
return args.Get(0).(types.Result), args.Error(1)
|
return args.Get(0).(types.Result), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockCNI) DelNetwork(net *libcni.NetworkConfig, rt *libcni.RuntimeConf) error {
|
func (m *MockCNI) AddNetworkList(ctx context.Context, net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) (types.Result, error) {
|
||||||
args := m.Called(net, rt)
|
args := m.Called(ctx, net, rt)
|
||||||
return args.Error(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockCNI) DelNetworkList(net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) error {
|
|
||||||
args := m.Called(net, rt)
|
|
||||||
return args.Error(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockCNI) AddNetworkList(net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) (types.Result, error) {
|
|
||||||
args := m.Called(net, rt)
|
|
||||||
return args.Get(0).(types.Result), args.Error(1)
|
return args.Get(0).(types.Result), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MockCNI) CheckNetworkList(ctx context.Context, net *libcni.NetworkConfigList, rt *libcni.RuntimeConf) error {
|
||||||
|
args := m.Called(ctx, net, rt)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockCNI) CheckNetwork(ctx context.Context, net *libcni.NetworkConfig, rt *libcni.RuntimeConf) error {
|
||||||
|
args := m.Called(ctx, net, rt)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockCNI) GetNetworkCachedResult(net *libcni.NetworkConfig, rt *libcni.RuntimeConf) (types.Result, error) {
|
||||||
|
args := m.Called(net, rt)
|
||||||
|
return args.Get(0).(types.Result), args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockCNI) ValidateNetworkList(ctx context.Context, net *libcni.NetworkConfigList) ([]string, error) {
|
||||||
|
args := m.Called(ctx, net)
|
||||||
|
return args.Get(0).([]string), args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockCNI) ValidateNetwork(ctx context.Context, net *libcni.NetworkConfig) ([]string, error) {
|
||||||
|
args := m.Called(ctx, net)
|
||||||
|
return args.Get(0).([]string), args.Error(0)
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@ limitations under the License.
|
|||||||
package kubenet
|
package kubenet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
@ -570,7 +571,7 @@ func (plugin *kubenetNetworkPlugin) addContainerToNetwork(config *libcni.Network
|
|||||||
// The network plugin can take up to 3 seconds to execute,
|
// The network plugin can take up to 3 seconds to execute,
|
||||||
// so yield the lock while it runs.
|
// so yield the lock while it runs.
|
||||||
plugin.mu.Unlock()
|
plugin.mu.Unlock()
|
||||||
res, err := plugin.cniConfig.AddNetwork(config, rt)
|
res, err := plugin.cniConfig.AddNetwork(context.TODO(), config, rt)
|
||||||
plugin.mu.Lock()
|
plugin.mu.Lock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error adding container to network: %v", err)
|
return nil, fmt.Errorf("Error adding container to network: %v", err)
|
||||||
@ -585,7 +586,7 @@ func (plugin *kubenetNetworkPlugin) delContainerFromNetwork(config *libcni.Netwo
|
|||||||
}
|
}
|
||||||
|
|
||||||
klog.V(3).Infof("Removing %s/%s from '%s' with CNI '%s' plugin and runtime: %+v", namespace, name, config.Network.Name, config.Network.Type, rt)
|
klog.V(3).Infof("Removing %s/%s from '%s' with CNI '%s' plugin and runtime: %+v", namespace, name, config.Network.Name, config.Network.Type, rt)
|
||||||
err = plugin.cniConfig.DelNetwork(config, rt)
|
err = plugin.cniConfig.DelNetwork(context.TODO(), config, rt)
|
||||||
// The pod may not get deleted successfully at the first time.
|
// The pod may not get deleted successfully at the first time.
|
||||||
// Ignore "no such file or directory" error in case the network has already been deleted in previous attempts.
|
// Ignore "no such file or directory" error in case the network has already been deleted in previous attempts.
|
||||||
if err != nil && !strings.Contains(err.Error(), "no such file or directory") {
|
if err != nil && !strings.Contains(err.Error(), "no such file or directory") {
|
||||||
|
@ -143,7 +143,7 @@ func TestTeardownCallsShaper(t *testing.T) {
|
|||||||
kubenet.bandwidthShaper = fshaper
|
kubenet.bandwidthShaper = fshaper
|
||||||
kubenet.hostportSyncer = hostporttest.NewFakeHostportSyncer()
|
kubenet.hostportSyncer = hostporttest.NewFakeHostportSyncer()
|
||||||
|
|
||||||
mockcni.On("DelNetwork", mock.AnythingOfType("*libcni.NetworkConfig"), mock.AnythingOfType("*libcni.RuntimeConf")).Return(nil)
|
mockcni.On("DelNetwork", mock.AnythingOfType("*context.emptyCtx"), mock.AnythingOfType("*libcni.NetworkConfig"), mock.AnythingOfType("*libcni.RuntimeConf")).Return(nil)
|
||||||
|
|
||||||
details := make(map[string]interface{})
|
details := make(map[string]interface{})
|
||||||
details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR] = "10.0.0.1/24"
|
details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR] = "10.0.0.1/24"
|
||||||
@ -247,7 +247,7 @@ func TestTearDownWithoutRuntime(t *testing.T) {
|
|||||||
existingContainerID := kubecontainer.BuildContainerID("docker", "123")
|
existingContainerID := kubecontainer.BuildContainerID("docker", "123")
|
||||||
kubenet.podIPs[existingContainerID] = tc.ip
|
kubenet.podIPs[existingContainerID] = tc.ip
|
||||||
|
|
||||||
mockcni.On("DelNetwork", mock.AnythingOfType("*libcni.NetworkConfig"), mock.AnythingOfType("*libcni.RuntimeConf")).Return(nil)
|
mockcni.On("DelNetwork", mock.AnythingOfType("*context.emptyCtx"), mock.AnythingOfType("*libcni.NetworkConfig"), mock.AnythingOfType("*libcni.RuntimeConf")).Return(nil)
|
||||||
|
|
||||||
if err := kubenet.TearDownPod("namespace", "name", existingContainerID); err != nil {
|
if err := kubenet.TearDownPod("namespace", "name", existingContainerID); err != nil {
|
||||||
t.Fatalf("Unexpected error in TearDownPod: %v", err)
|
t.Fatalf("Unexpected error in TearDownPod: %v", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user