add validation for CNI config before loading and fix some typo

1. add validation for CNI config before loading
2. make some CNI capabilities constants
3. add Capabilities field to cniNetwork struct

Signed-off-by: Bruce Ma <brucema19901024@gmail.com>
This commit is contained in:
Bruce Ma 2019-07-23 21:15:17 +08:00
parent 55807b71ad
commit 9903cb3ad3
2 changed files with 35 additions and 21 deletions

View File

@ -19,6 +19,7 @@ go_library(
"//pkg/kubelet/container:go_default_library", "//pkg/kubelet/container:go_default_library",
"//pkg/kubelet/dockershim/network:go_default_library", "//pkg/kubelet/dockershim/network:go_default_library",
"//pkg/util/bandwidth:go_default_library", "//pkg/util/bandwidth:go_default_library",
"//pkg/util/slice:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2:go_default_library", "//staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2:go_default_library",
"//vendor/github.com/containernetworking/cni/libcni:go_default_library", "//vendor/github.com/containernetworking/cni/libcni:go_default_library",

View File

@ -19,7 +19,6 @@ package cni
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"math" "math"
"sort" "sort"
@ -36,6 +35,7 @@ import (
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/kubelet/dockershim/network" "k8s.io/kubernetes/pkg/kubelet/dockershim/network"
"k8s.io/kubernetes/pkg/util/bandwidth" "k8s.io/kubernetes/pkg/util/bandwidth"
utilslice "k8s.io/kubernetes/pkg/util/slice"
utilexec "k8s.io/utils/exec" utilexec "k8s.io/utils/exec"
) )
@ -46,6 +46,13 @@ const (
// defaultSyncConfigPeriod is the default period to sync CNI config // defaultSyncConfigPeriod is the default period to sync CNI config
// TODO: consider making this value configurable or to be a more appropriate value. // TODO: consider making this value configurable or to be a more appropriate value.
defaultSyncConfigPeriod = time.Second * 5 defaultSyncConfigPeriod = time.Second * 5
// supported capabilities
// https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md
portMappingsCapability = "portMappings"
ipRangesCapability = "ipRanges"
bandwidthCapability = "bandwidth"
dnsCapability = "dns"
) )
type cniNetworkPlugin struct { type cniNetworkPlugin struct {
@ -69,6 +76,7 @@ type cniNetwork struct {
name string name string
NetworkConfig *libcni.NetworkConfigList NetworkConfig *libcni.NetworkConfigList
CNIConfig libcni.CNI CNIConfig libcni.CNI
Capabilities []string
} }
// cniPortMapping maps to the standard CNI portmapping Capability // cniPortMapping maps to the standard CNI portmapping Capability
@ -149,9 +157,11 @@ func getDefaultCNINetwork(confDir string, binDirs []string) (*cniNetwork, error)
case err != nil: case err != nil:
return nil, err return nil, err
case len(files) == 0: case len(files) == 0:
return nil, fmt.Errorf("No networks found in %s", confDir) return nil, fmt.Errorf("no networks found in %s", confDir)
} }
cniConfig := &libcni.CNIConfig{Path: binDirs}
sort.Strings(files) sort.Strings(files)
for _, confFile := range files { for _, confFile := range files {
var confList *libcni.NetworkConfigList var confList *libcni.NetworkConfigList
@ -185,16 +195,24 @@ func getDefaultCNINetwork(confDir string, binDirs []string) (*cniNetwork, error)
continue continue
} }
// Before using this CNI config, we have to validate it to make sure that
// all plugins of this config exist on disk
caps, err := cniConfig.ValidateNetworkList(context.TODO(), confList)
if err != nil {
klog.Warningf("Error validating CNI config %v: %v", confList, err)
continue
}
klog.V(4).Infof("Using CNI configuration file %s", confFile) klog.V(4).Infof("Using CNI configuration file %s", confFile)
network := &cniNetwork{ return &cniNetwork{
name: confList.Name, name: confList.Name,
NetworkConfig: confList, NetworkConfig: confList,
CNIConfig: &libcni.CNIConfig{Path: binDirs}, CNIConfig: cniConfig,
} Capabilities: caps,
return network, nil }, nil
} }
return nil, fmt.Errorf("No valid networks found in %s", confDir) return nil, fmt.Errorf("no valid networks found in %s", confDir)
} }
func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error {
@ -236,18 +254,13 @@ func (plugin *cniNetworkPlugin) setDefaultNetwork(n *cniNetwork) {
func (plugin *cniNetworkPlugin) checkInitialized() error { func (plugin *cniNetworkPlugin) checkInitialized() error {
if plugin.getDefaultNetwork() == nil { if plugin.getDefaultNetwork() == nil {
return errors.New("cni config uninitialized") return fmt.Errorf("cni config uninitialized")
} }
// If the CNI configuration has the ipRanges capability, we need a PodCIDR assigned if utilslice.ContainsString(plugin.getDefaultNetwork().Capabilities, ipRangesCapability, nil) && plugin.podCidr == "" {
for _, p := range plugin.getDefaultNetwork().NetworkConfig.Plugins { return fmt.Errorf("cni config needs ipRanges but no PodCIDR set")
if p.Network.Capabilities["ipRanges"] {
if plugin.podCidr == "" {
return errors.New("no PodCIDR set")
}
break
}
} }
return nil return nil
} }
@ -395,12 +408,12 @@ func (plugin *cniNetworkPlugin) buildCNIRuntimeConf(podName string, podNs string
}) })
} }
rt.CapabilityArgs = map[string]interface{}{ rt.CapabilityArgs = map[string]interface{}{
"portMappings": portMappingsParam, portMappingsCapability: portMappingsParam,
} }
ingress, egress, err := bandwidth.ExtractPodBandwidthResources(annotations) ingress, egress, err := bandwidth.ExtractPodBandwidthResources(annotations)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error reading pod bandwidth annotations: %v", err) return nil, fmt.Errorf("failed to get pod bandwidth from annotations: %v", err)
} }
if ingress != nil || egress != nil { if ingress != nil || egress != nil {
bandwidthParam := cniBandwidthEntry{} bandwidthParam := cniBandwidthEntry{}
@ -415,11 +428,11 @@ func (plugin *cniNetworkPlugin) buildCNIRuntimeConf(podName string, podNs string
bandwidthParam.EgressRate = int(egress.Value()) bandwidthParam.EgressRate = int(egress.Value())
bandwidthParam.EgressBurst = math.MaxInt32 // no limit bandwidthParam.EgressBurst = math.MaxInt32 // no limit
} }
rt.CapabilityArgs["bandwidth"] = bandwidthParam rt.CapabilityArgs[bandwidthCapability] = bandwidthParam
} }
// Set the PodCIDR // Set the PodCIDR
rt.CapabilityArgs["ipRanges"] = [][]cniIPRange{{{Subnet: plugin.podCidr}}} rt.CapabilityArgs[ipRangesCapability] = [][]cniIPRange{{{Subnet: plugin.podCidr}}}
// Set dns capability args. // Set dns capability args.
if dnsOptions, ok := options["dns"]; ok { if dnsOptions, ok := options["dns"]; ok {
@ -429,7 +442,7 @@ func (plugin *cniNetworkPlugin) buildCNIRuntimeConf(podName string, podNs string
return nil, fmt.Errorf("failed to unmarshal dns config %q: %v", dnsOptions, err) return nil, fmt.Errorf("failed to unmarshal dns config %q: %v", dnsOptions, err)
} }
if dnsParam := buildDNSCapabilities(&dnsConfig); dnsParam != nil { if dnsParam := buildDNSCapabilities(&dnsConfig); dnsParam != nil {
rt.CapabilityArgs["dns"] = *dnsParam rt.CapabilityArgs[dnsCapability] = *dnsParam
} }
} }