• CNI插件源码示例,对于github.com/rajatchopra/ocicni库的分析


    CNI插件初始化

    // ocicni.go

    1、func InitCNI(pluginDir string) (CNIPlugin, error)

    (1)、先调用plugin := probeNetworkingPluginsWithVendorCNIDirPrefix(pluginDir, "")

    先初步创建一个默认的cniNetworkPlugin的结构,并调用plugin.nsenterPath, err = exec.LookPath("nsenter")

    (2)、调用err = getDefaultCNINetwork(plugin.pluginDir, plugin.vendorCNIDirPrefix),检查默认的network

    是否存在,若不存在,则停止CNI插件的搜索,直接返回一个&cniNoOp{}结构

    (3)、生成一个goroutine,调用plugin.SyncNetworConfig()周期性地和pluginDir进行同步,从而检查网络状态的更新

    (4)、最后,return plugin, nil

    cniNetworkPlugin结构如下所示:

    type cniNetworkPlugin struct {
      loNetwork      *cniNetwork
      sync.RWMutex
      defaultNetwork   *cniNetwork
      nsenterPath     string   pluginDir      string   vendorCNIDirPrefix string }

      

    cniNetwork结构如下所示:

    type cniNetwork struct {
      name      string
      NetworkConfig  *libcni.NetworkConfig
      CNIConfig    libcni.CNI
    }
    

      

    // ocicni.go

    2、func probeNetworkPluginsWithVendorCNIDirPrefix(pluginDir, vendorCNIDirPrefix string) (*cniNetworkPlugin)

    (1)、创建plugin := &cniNetworkPlugin{

      defaultNetwork:      nil,

      loNetwork:          getLoNetwork(vendorCNIDirPrefix),

      pluginDir:          pluginDir,

      vendorCNIDirPrefix:    vendorCNIDirPrefix,

    }

    (2)、调用plugin.syncNetworkConfig()  ---> sync NetworkConfig in best effort during probing

    (3)、最后,return plugin

    // ocicni.go

    3、func getLoNetwork(vendorDirPrefix string) *cniNetwork

    (1)、调用loConfig,err := libcni.ConfFromBytes([]byte(`{"cniVersion": "0.1.0", "name": "cni-loopback", "type": "loopback"}`))

    (2)、调用cninet := &libcni.CNIConfig{Path: []string{vendorCNIDir(vendorDirPrefix, loConfig.Network.Type), DefaultCNIDir}},其中vendorCNIDir返回的就是这样一个目录:$vendorDirPrefix/opt/$type/bin

    (3)、创建loNetwork := cniNetwork{

      name:      "lo"

      NetworkConfig:   loConfig,

      CNIConfig:    cninet

    }

    再return loNetwork

    // ocicni.go

    4、func (plugin *cniNetworkPlugin) syncNetworkConfig()

    该函数仅仅调用network, err := getDefaultCNINetwork(plugin.pluginDir, plugin.vendorCNIDirPrefix)

    再调用plugin.setDefaultNetwork(network)

    // ocicni.go

    5、func getDefaultCNINetwork(pluginDir, vendorCNIDirPrefix string) (*cniNetwork, error)

    (1)、当pluginDir为""时,设置pluginDir = DefaultNetDir

    (2)、调用files, err := libcni.ConfFiles(pluginDir),从pluginDir中加载文件,若err不为nil,或者len(files) == 0,则报错

    (3)、遍历files,调用conf, err := libcni.ConfFromFile(confFile),加载CNI config file

    再设置cninet := &libcni.CNIConfig{Path: []string{DefaultCNIDir, vendorDir},}

    最后设置network := &cniNetwork{name: conf.Network.Name, NetworkConfig: conf, CNIConfig: cninet}

    // ocicni.go

    6、func setDefaultNetwork(n *cniNetwork)

    该函数仅仅设置plugin.defaultNetwork = n而已

    CNI插件创建POD

    // cri-o端的调用为:
    
    podNamespace := ""
    
    s.netPlugin.SetUpPod(netNsPath, podNamespace, id, containerName)
    

    // ocicni.go

    1、func (plugin *cniNetworkPlugin) SetUpPod(netnsPath string, namespace string, name string, id string) error

    (1)、首先调用plugin.checkInitialized(),该函数确定plugin.defaultNetwork是否为nil,若为nil则报错

    (2)、调用plugin.loNetwork.addToNetwork(name, namespace, id, netnsPath)

    (3)、调用plugin.getDefaultNetwork().addToNetwork(name, namespace, id, netnsPath)

    // ocicni.go

    2、func (network *cniNetwork) addToNetwork(podName string, podNamespace string, podInfraContainerID string, podNetnsPath string) (*cnitypes.Result, error)

    (1)、调用rt, err := buildCNIRuntimeConf(podName, podNamespace, podInfraContainerID, podNetnsPath)

    (2)、调用netconf, cninet := network.NetworkConfig, network.CNIConfig

    (3)、调用res, err := cninet.AddNetwork(netconf, rt)

    (4)、最后return res, nil

    // ocicni.go

    3、func buildCNIRuntimeConf(podName string, podNs string, podInfraContainerID string, podNetnsPath string) (*libcni.RuntimeConf, error)

    该函数仅仅创建rt := &libcni.RuntimeConf{

      ContainerID:  podInfraContainerID,

      NetNS:       podNetnsPath,

      IfName:     DefaultInterfaceName,

      Args:    [][2]string{

          {"IgnoreUnknown", "1"},

          {"K8S_POD_NAMESPACE", podNs},

          {"K8S_POD_NAME", podName},

          {"K8S_POD_INFRA_CONTAINER_ID", podInfraContainerID},

      }

    }

    最后,return rt, nil

    获取pod的网络状态

    1、func (plugin *cniNetworkPlugin) GetContainerNetworkStatus(netnsPath string, namespace string, name string, id string) (string, error)

    该函数先调用ip, err := getContainerIP(plugin.nsenterPath, netnsPath, DefaultInterfaceName, "-4")

    最后return ip.String(), nil

  • 相关阅读:
    性能测试基本功 手动配置nginx+phpcgi+zend+mysql
    MySQL的show full processlist命令
    LoadRunner测试Webservices的例子
    Firefox 5 公开测试下载
    Shunra 即将发布 PerformanceSuite 7.0 和NetworkCatcher 7.0
    LoadRunner常见问题
    动态生成的图片保存成png格式
    如何解决ASP.NET程序安装到繁体系统上的乱码问题
    在Ubuntu上下载、编译和安装Android最新源代码
    腾讯微博api的蛋疼问题
  • 原文地址:https://www.cnblogs.com/YaoDD/p/6252272.html
Copyright © 2020-2023  润新知