Skip to content

Commit

Permalink
Merge dfe35bb into ad50ff5
Browse files Browse the repository at this point in the history
  • Loading branch information
s1061123 committed Oct 18, 2018
2 parents ad50ff5 + dfe35bb commit 915a316
Show file tree
Hide file tree
Showing 6 changed files with 339 additions and 48 deletions.
54 changes: 48 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,54 @@ $ kubectl exec -it samplepod -- ip a

## Network configuration reference

- name (string, required): the name of the network
- type (string, required): "multus"
- kubeconfig (string, optional): kubeconfig file for the out of cluster communication with kube-apiserver. See the example [kubeconfig](https://github.com/intel/multus-cni/blob/master/doc/node-kubeconfig.yaml)
- delegates (([]map,required): number of delegate details in the Multus
- capabilities ({}list, optional): [capabilities](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md#dynamic-plugin-specific-fields-capabilities--runtime-configuration) supported by at least one of the delegates. (NOTE: Multus only supports portMappings capability for now). See the [example](https://github.com/intel/multus-cni/blob/master/examples/multus-ptp-portmap.conf).
Following is the example of multus config file, in `/etc/cni/net.d/`.
```
{
"name": "node-cni-network",
"type": "multus",
"kubeconfig": "/etc/kubernetes/node-kubeconfig.yaml",
"confDir": "/etc/cni/multus/net.d",
"cniDir": "/var/lib/cni/multus",
"binDir": "/opt/cni/bin",
"logFile": "/var/log/multus.log",
"logLevel": "debug",
/* NOTE: you can set clusterNetwork+defaultNetworks OR delegates!! (this is only for manual) */
"clusterNetwork": "defaultCRD",
"defaultNetworks": ["sidecarCRD", "flannel"],
"delegates": [{
"type": "weave-net",
"hairpinMode": true
}, {
"type": "macvlan",
... (snip)
}]
}
```

- `name` (string, required): the name of the network
- `type` (string, required): "multus"
- `confDir` (string, optional): directory for CNI config file that multus reads. default `/etc/cni/multus/net.d`
- `cniDir` (string, optional): Multus CNI data directory, default `/var/lib/cni/multus`
- `binDir` (string, optional): directory for CNI plugins which multus calls. default `/opt/cni/bin`
- `kubeconfig` (string, optional): kubeconfig file for the out of cluster communication with kube-apiserver. See the example [kubeconfig](https://github.com/intel/multus-cni/blob/master/doc/node-kubeconfig.yaml). If you would like to use CRD (i.e. network attachment definition), this is required
- `logFile` (string, optional): file path for log file. multus puts log in given file
- `logLevel` (string, optional): logging level ("debug", "error" or "panic")
- `capabilities` ({}list, optional): [capabilities](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md#dynamic-plugin-specific-fields-capabilities--runtime-configuration) supported by at least one of the delegates. (NOTE: Multus only supports portMappings capability for now). See the [example](https://github.com/intel/multus-cni/blob/master/examples/multus-ptp-portmap.conf).

User should chose following parameters combination (`clusterNetwork`+`defaultNetworks` or `delegates`):

- `clusterNetwork` (string, required): default CNI network for pods, used in kubernetes cluster (Pod IP and so on): name of network-attachment-definition, CNI json file name (without extention, .conf/.conflist) or directory for CNI config file
- `defaultNetworks` ([]string, required): default CNI network attachment: name of network-attachment-definition, CNI json file name (without extention, .conf/.conflist) or directory for CNI config file
- `delegates` ([]map,required): number of delegate details in the Multus

### Network selection flow of clusterNetwork/defaultNetworks

Multus will find network for clusterNetwork/defaultNetworks as following sequences:

1. CRD object for given network name
1. CNI json config file in `confDir`. Given name should be without extention, like .conf/.conflist. (e.g. "test" for "test.conf")
1. Directory for CNI json config file. Multus will find alphabetically first file for the network.
1. Multus raise error message

## Usage with Kubernetes CRD based network objects

Expand Down Expand Up @@ -616,7 +659,6 @@ pod "multus-test" created
- [Node Feature Discovery](https://github.com/kubernetes-incubator/node-feature-discovery)
- [CPU Manager for Kubernetes](https://github.com/Intel-Corp/CPU-Manager-for-Kubernetes)


## Need help

- Read [Containers Experience Kits](https://networkbuilders.intel.com/network-technologies/container-experience-kits)
Expand Down
125 changes: 116 additions & 9 deletions k8sclient/k8sclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ func getCNIConfigFromFile(name string, confdir string) ([]byte, error) {
return nil, logging.Errorf("Error loading CNI conflist file %s: %v", confFile, err)
}

if confList.Name == name {
if confList.Name == name || name == "" {
return confList.Bytes, nil
}

Expand All @@ -265,7 +265,7 @@ func getCNIConfigFromFile(name string, confdir string) ([]byte, error) {
return nil, logging.Errorf("Error loading CNI config file %s: %v", confFile, err)
}

if conf.Network.Name == name {
if conf.Network.Name == name || name == "" {
// Ensure the config has a "type" so we know what plugin to run.
// Also catches the case where somebody put a conflist into a conf file.
if conf.Network.Type == "" {
Expand Down Expand Up @@ -396,7 +396,7 @@ type KubeClient interface {
func GetK8sArgs(args *skel.CmdArgs) (*types.K8sArgs, error) {
k8sArgs := &types.K8sArgs{}

logging.Debugf("GetK8sNetwork: %v", args)
logging.Debugf("GetK8sArgs: %v", args)
err := cnitypes.LoadArgs(args.Args, k8sArgs)
if err != nil {
return nil, err
Expand All @@ -407,11 +407,11 @@ func GetK8sArgs(args *skel.CmdArgs) (*types.K8sArgs, error) {

// Attempts to load Kubernetes-defined delegates and add them to the Multus config.
// Returns the number of Kubernetes-defined delegates added or an error.
func TryLoadK8sDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient KubeClient) (int, *clientInfo, error) {
func TryLoadPodDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient KubeClient) (int, *clientInfo, error) {
var err error
clientInfo := &clientInfo{}

logging.Debugf("TryLoadK8sDelegates: %v, %v, %v", k8sArgs, conf, kubeClient)
logging.Debugf("TryLoadPodDelegates: %v, %v, %v", k8sArgs, conf, kubeClient)
kubeClient, err = GetK8sClient(conf.Kubeconfig, kubeClient)
if err != nil {
return 0, nil, err
Expand All @@ -426,7 +426,7 @@ func TryLoadK8sDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient
}

setKubeClientInfo(clientInfo, kubeClient, k8sArgs)
delegates, err := GetK8sNetwork(kubeClient, k8sArgs, conf.ConfDir)
delegates, err := GetPodNetwork(kubeClient, k8sArgs, conf.ConfDir)
if err != nil {
if _, ok := err.(*NoK8sNetworkError); ok {
return 0, clientInfo, nil
Expand Down Expand Up @@ -479,8 +479,8 @@ func GetK8sClient(kubeconfig string, kubeClient KubeClient) (KubeClient, error)
return &defaultKubeClient{client: client}, nil
}

func GetK8sNetwork(k8sclient KubeClient, k8sArgs *types.K8sArgs, confdir string) ([]*types.DelegateNetConf, error) {
logging.Debugf("GetK8sNetwork: %v, %v, %v", k8sclient, k8sArgs, confdir)
func GetPodNetwork(k8sclient KubeClient, k8sArgs *types.K8sArgs, confdir string) ([]*types.DelegateNetConf, error) {
logging.Debugf("GetPodNetwork: %v, %v, %v", k8sclient, k8sArgs, confdir)

netAnnot, defaultNamespace, podID, err := getPodNetworkAnnotation(k8sclient, k8sArgs)
if err != nil {
Expand Down Expand Up @@ -509,11 +509,118 @@ func GetK8sNetwork(k8sclient KubeClient, k8sArgs *types.K8sArgs, confdir string)
for _, net := range networks {
delegate, updatedResourceMap, err := getKubernetesDelegate(k8sclient, net, confdir, podID, resourceMap)
if err != nil {
return nil, logging.Errorf("GetK8sNetwork: failed getting the delegate: %v", err)
return nil, logging.Errorf("GetPodNetwork: failed getting the delegate: %v", err)
}
delegates = append(delegates, delegate)
resourceMap = updatedResourceMap
}

return delegates, nil
}

func getDefaultNetDelegateCRD(client KubeClient, net string, confdir string) (*types.DelegateNetConf, error) {
logging.Debugf("getDefaultNetDelegate: %v, %v, %s", client, net, confdir)
rawPath := fmt.Sprintf("/apis/k8s.cni.cncf.io/v1/namespaces/%s/network-attachment-definitions/%s", "default", net)
netData, err := client.GetRawWithPath(rawPath)
if err != nil {
return nil, logging.Errorf("getDefaultNetDelegate: failed to get network resource, refer Multus README.md for the usage guide: %v", err)
}

customResource := &types.NetworkAttachmentDefinition{}
if err := json.Unmarshal(netData, customResource); err != nil {
return nil, logging.Errorf("getDefaultNetDelegate: failed to get the netplugin data: %v", err)
}

configBytes, err := cniConfigFromNetworkResource(customResource, confdir)
if err != nil {
return nil, err
}

delegate, err := types.LoadDelegateNetConf(configBytes, "", "")
if err != nil {
return nil, err
}

return delegate, nil
}

func getNetDelegate(client KubeClient, netname string, confdir string) (*types.DelegateNetConf, error) {
logging.Debugf("getNetDelegate: %v, %v, %v", client, netname, confdir)
// option1) search CRD object for the network
delegate, err := getDefaultNetDelegateCRD(client, netname, confdir)
if err == nil {
return delegate, nil
}

// option2) search CNI json config file
var configBytes []byte
configBytes, err = getCNIConfigFromFile(netname, confdir)
if err == nil {
delegate, err := types.LoadDelegateNetConf(configBytes, "", "")
if err != nil {
return nil, err
}
return delegate, nil
}

// option3) search directry
fInfo, err := os.Stat(netname)
if err == nil {
if fInfo.IsDir() {
files, err := libcni.ConfFiles(netname, []string{".conf", ".conflist"})
if len(files) > 0 {
var configBytes []byte
configBytes, err = getCNIConfigFromFile("", netname)
if err == nil {
delegate, err := types.LoadDelegateNetConf(configBytes, "", "")
if err != nil {
return nil, err
}
return delegate, nil
}
return nil, err
}
}
}
return nil, logging.Errorf("getNetDelegate: cannot find network: %v", netname)
}

// GetDefaultNetwork parses 'defaultNetwork' config, gets network json and put it into netconf.Delegates.
func GetDefaultNetworks(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient KubeClient) error {
logging.Debugf("GetDefaultNetworks: %v, %v, %v", k8sArgs, conf, kubeClient)
var delegates []*types.DelegateNetConf

kubeClient, err := GetK8sClient(conf.Kubeconfig, kubeClient)
if err != nil {
return err
}
if kubeClient == nil {
if len(conf.Delegates) == 0 {
// No available kube client and no delegates, we can't do anything
return logging.Errorf("must have either Kubernetes config or delegates, refer Multus README.md for the usage guide")
}
return nil
}

delegate, err := getNetDelegate(kubeClient, conf.ClusterNetwork, conf.ConfDir)
if err != nil {
return err
}
delegate.MasterPlugin = true
delegates = append(delegates, delegate)

//need to revisit
for _, netname := range conf.DefaultNetworks {
delegate, err := getNetDelegate(kubeClient, netname, conf.ConfDir)
if err != nil {
return err
}
delegates = append(delegates, delegate)
}

if err = conf.AddDelegates(delegates); err != nil {
return err
}

return nil
}

0 comments on commit 915a316

Please sign in to comment.