摘要
kubernetes有3个神奇插口,CNI、CRI和CSI,它们分别负责网络、运作和储存。今天我们来剖析CNI,看看它是啥,以及k8s是怎么用它来搭建和删掉pod网络的。让我们一起揭开这个神秘面纱吧!
正文
关系blog:kubernetes/k8s CSI剖析-器皿储存接口分析
kubernetes/k8s CRI剖析-器皿运作时接口分析
简述
kubernetes的设计方案初心是适用可插下构架,进而有利于拓展kubernetes的作用。在这里构架观念下,kubernetes给予了3个特殊作用的插口,分别是器皿网线端口CNI、器皿运作时插口CRI和器皿储存插口CSI。kubernetes根据启用这好多个插口,来进行相对应的作用。
下边大家来对器皿运作时插口CNI来做一下详细介绍与剖析。
CNI是啥
CNI,全名是 Container Network Interface,即器皿网线端口。
CNI是K8s 中规范的启用互联网完成的插口。Kubelet 根据这一规范的插口来启用不一样的互联网软件以完成不一样的网络配置方法。
CNI互联网软件是一个可执行程序,是遵循器皿网线端口(CNI)标准的互联网软件。普遍的 CNI互联网软件包含 Calico、flannel、Terway、Weave Net等。
当kubelet挑选应用CNI种类的互联网软件时(根据kubelet运行主要参数特定),kubelet在建立pod、删掉pod的情况下,会启用CNI互联网软件来做pod的搭建互联网和消毁互联网等实际操作。
kubelet的互联网软件
kubelet的互联网软件有下列3种种类:
(1)CNI;
(2)kubenet;
(3)Noop,意味着不配备互联网软件。
这儿关键对kubelet中CNI有关的源代码开展剖析。
CNI构架
kubelet建立/删掉pod时,会启用CRI,随后CRI会启用CNI来开展pod网络的搭建/删掉。
kubelet搭建pod网络的大概全过程
(1)kubelet先根据CRI建立pause器皿(pod sandbox),转化成network namespace;
(2)kubelet依据运行参数配置启用实际的互联网软件如CNI互联网软件;
(3)互联网软件给pause器皿(pod sandbox)配备互联网;
(4)pod 中别的的器皿都和pause器皿(pod sandbox)分享网络。
kubelet中cni有关的源代码剖析
kubelet的cni源代码剖析包含以下几一部分:
(1)cni有关运行主要参数剖析;
(2)重要struct/interface剖析;
(3)cni复位剖析;
(4)cni搭建pod网络剖析;
(5)cni消毁pod网络剖析。
根据tag v1.17.4
https://GitHub.com/kubernetes/kubernetes/releases/tag/v1.17.4
1.kubelet部件cni有关运行主要参数剖析
kubelet部件cni有关运行主要参数有关编码以下:
// pkg/kubelet/config/flags.go
func (s *ContainerRuntimeOptions) AddFlags(fs *pflag.FlagSet) {
...
// Network plugin settings for Docker.
fs.StringVar(&s.NetworkPluginName, "network-plugin", s.NetworkPluginName, fmt.Sprintf("<Warning: Alpha feature> The name of the network plugin to be invoked for various events in kubelet/pod lifecycle. %s", dockerOnlyWarning))
fs.StringVar(&s.CNIConfDir, "cni-conf-dir", s.CNIConfDir, fmt.Sprintf("<Warning: Alpha feature> The full path of the directory in which to search for CNI config files. %s", dockerOnlyWarning))
fs.StringVar(&s.CNIBinDir, "cni-bin-dir", s.CNIBinDir, fmt.Sprintf("<Warning: Alpha feature> A comma-separated list of full paths of directories in which to search for CNI plugin binaries. %s", dockerOnlyWarning))
fs.StringVar(&s.CNICacheDir, "cni-cache-dir", s.CNICacheDir, fmt.Sprintf("<Warning: Alpha feature> The full path of the directory in which CNI should store cache files. %s", dockerOnlyWarning))
fs.Int32Var(&s.NetworkPluginMTU, "network-plugin-mtu", s.NetworkPluginMTU, fmt.Sprintf("<Warning: Alpha feature> The MTU to be passed to the network plugin, to override the default. Set to 0 to use the default 1460 MTU. %s", dockerOnlyWarning))
...
}
cni有关运行主要参数的初始值在NewContainerRuntimeOptions
涵数中设定。
// cmd/kubelet/app/options/container_runtime.go
// NewContainerRuntimeOptions will create a new ContainerRuntimeOptions with
// default values.
func NewContainerRuntimeOptions() *config.ContainerRuntimeOptions {
dockerEndpoint := ""
if runtime.GOOS != "Windows" {
dockerEndpoint = "unix:///var/run/docker.sock"
}
return &config.ContainerRuntimeOptions{
ContainerRuntime: kubetypes.DockerContainerRuntime,
RedirectContainerStreaming: false,
DockerEndpoint: dockerEndpoint,
DockershimRootDirectory: "/var/lib/dockershim",
PodSandboxImage: defaultPodSandboxImage,
ImagePullProgressDeadline: metav1.Duration{Duration: 1 * time.Minute},
ExperimentalDockershim: false,
//Alpha feature
CNIBinDir: "/opt/cni/bin",
CNIConfDir: "/etc/cni/net.d",
CNICacheDir: "/var/lib/cni/cache",
}
}
下边来简易剖析好多个较为关键的cni有关运行主要参数:
(1)--network-plugin
:特定要应用的互联网软件种类,可选值cni
、kubenet
、""
,默认设置 为空串,意味着Noop,即不配备互联网软件(不搭建pod网络)。这里配备数值cni
时,即特定kubelet应用的互联网软件种类为cni
。
(2)--cni-conf-dir
:CNI 环境变量所属途径。初始值:/etc/cni/net.d
。
(3)--cni-bin-dir
:CNI 软件的可执行程序所属途径,kubelet 将在这里途径中搜索 CNI 软件的可执行程序来实行pod的互联网实际操作。初始值:/opt/cni/bin
。
2.重要struct/interface剖析
interface NetworkPlugin
先看来下重要的interface:NetworkPlugin
。
NetworkPlugin interface申明了kubelet互联网软件的一些操作步骤,不一样种类的互联网软件只必须完成这种方式就可以,在其中最重要的便是SetUpPod
与TearDownPod
方式,功效分别是搭建pod网络与消毁pod网络,cniNetworkPlugin
完成了该interface。
// pkg/kubelet/dockershim/network/plugins.go
// NetworkPlugin is an interface to network plugins for the kubelet
type NetworkPlugin interface {
// Init initializes the plugin. This will be called exactly once
// before any other methods are called.
Init(host Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error
// Called on various events like:
// NET_PLUGIN_EVENT_POD_CIDR_CHANGE
Event(name string, details map[string]interface{})
// Name returns the plugin's name. This will be used when searching
// for a plugin by name, e.g.
Name() string
// Returns a set of NET_PLUGIN_CAPABILITY_*
Capabilities() utilsets.Int
// SetUpPod is the method called after the infra container of
// the pod has been created but before the other containers of the
// pod are launched.
SetUpPod(namespace string, name string, podSandboxID kubecontainer.ContainerID, annotations, options map[string]string) error
// TearDownPod is the method called before a pod's infra container will be deleted
TearDownPod(namespace string, name string, podSandboxID kubecontainer.ContainerID) error
// GetPodNetworkStatus is the method called to obtain the ipv4 or ipv6 addresses of the container
GetPodNetworkStatus(namespace string, name string, podSandboxID kubecontainer.ContainerID) (*PodNetworkStatus, error)
// Status returns error if the network plugin is in error state
Status() error
}
struct cniNetworkPlugin
cniNetworkPlugin struct完成了NetworkPlugin interface
,完成了SetUpPod
与TearDownPod
等方式。
// pkg/kubelet/dockershim/network/cni/cni.go
type cniNetworkPlugin struct {
network.NoopNetworkPlugin
loNetwork *cniNetwork
sync.RWMutex
defaultNetwork *cniNetwork
host network.Host
execer utilexec.Interface
nsenterPath string
confDir string
binDirs []string
cacheDir string
podCidr string
}
struct PluginManager
struct PluginManager中的plugin
特性是interface NetworkPlugin
种类,能够 传到实际的互联网软件完成,如cniNetworkPlugin struct
。
// pkg/kubelet/dockershim/network/plugins.go
// The PluginManager wraps a kubelet network plugin and provides synchronization
// for a given pod's network operations. Each pod's setup/teardown/status operations
// are synchronized against each other, but network operations of other pods can
// proceed in parallel.
type PluginManager struct {
// Network plugin being wrapped
plugin NetworkPlugin
// Pod list and lock
podsLock sync.Mutex
pods map[string]*podLock
}
struct dockerService
struct dockerService实际上在CRI剖析的博闻一部分有做了深入分析,能够 去回望一下,下边再简易做一下详细介绍。
struct dockerService完成了CRI shim服务器端的器皿运作时插口及其器皿镜像系统插口,因此 其意味着了dockershim(kubelet内嵌的CRI shim)的服务器端。
struct dockerService中的network
特性是struct PluginManager
种类,在该建筑结构复位的时候会将实际的互联网软件建筑结构如struct cniNetworkPlugin
储存进该特性。
建立pod、删掉pod的时候会依据dockerService
建筑结构的network
特性里边储存的实际的互联网软件建筑结构,去启用某一实际互联网软件(如cniNetworkPlugin
)的SetUpPod
、TearDownPod
方式来搭建pod的互联网、消毁pod的互联网。
// pkg/kubelet/dockershim/docker_service.go
type dockerService struct {
client libdocker.Interface
os kubecontainer.OSInterface
podSandboxImage string
streamingRuntime *streamingRuntime
streamingServer streaming.Server
network *network.PluginManager
// Map of podSandboxID :: network-is-ready
networkReady map[string]bool
networkReadyLock sync.Mutex
containerManager cm.ContainerManager
// cgroup driver used by Docker runtime.
cgroupDriver string
checkpointManager checkpointmanager.CheckpointManager
// caches the version of the runtime.
// To be compatible with multiple docker versions, we need to perform
// version checking for some operations. Use this cache to avoid querying
// the docker daemon every time we need to do such checks.
versionCache *cache.ObjectCache
// startLocalStreamingServer indicates whether dockershim should start a
// streaming server on localhost.
startLocalStreamingServer bool
// containerCleanupInfos maps container IDs to the `containerCleanupInfo` structs
// needed to clean up after containers have been removed.
// (see `applyPlatformSpecificDockerConfig` and `performPlatformSpecificContainerCleanup`
// methods for more info).
containerCleanupInfos map[string]*containerCleanupInfo
}
3.cni复位剖析
Kubelet 运行全过程中对于互联网关键做下列流程,分别是探头获得当今自然环境的互联网软件及其复位互联网软件(仅有当器皿运作时挑选为内嵌dockershim时,才会做CNI的复位实际操作,将CNI复位进行后交到dockershim应用)。
cni复位的启用链:
main (cmd/kubelet/kubelet.go)
-> NewKubeletCommand (cmd/kubelet/app/server.go)
-> Run (cmd/kubelet/app/server.go)
-> run (cmd/kubelet/app/server.go)
-> RunKubelet (cmd/kubelet/app/server.go)
-> CreateAndInitKubelet(cmd/kubelet/app/server.go)
-> kubelet.NewMainKubelet(pkg/kubelet/kubelet.go)
-> cni.ProbeNetworkPlugins & network.InitNetworkPlugin(pkg/kubelet/network/plugins.go)
启用链较长,这儿直接进入重要的涵数NewMainKubelet
开展剖析。
NewMainKubelet
NewMainKubelet涵数中关键见到dockershim.NewDockerService
启用。
// pkg/kubelet/kubelet.go
// NewMainKubelet instantiates a new Kubelet object along with all the required internal modules.
// No initialization of Kubelet and its modules should happen here.
func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,...) {
...
switch containerRuntime {
case kubetypes.DockerContainerRuntime:
// Create and start the CRI shim running as a grpc server.
streamingConfig := getStreamingConfig(kubeCfg, kubeDeps, crOptions)
ds, err := dockershim.NewDockerService(kubeDeps.DockerClientConfig, crOptions.PodSandboxImage, streamingConfig,
&pluginSettings, runtimeCgroups, kubeCfg.CgroupDriver, crOptions.DockershimRootDirectory, !crOptions.RedirectContainerStreaming)
...
}
这儿对自变量containerRuntime
值相当于docker
时做剖析,即kubelet运行主要参数--container-runtime
数值docker
,这时候kubelet会应用内嵌的CRI shim
即dockershim
做为器皿运作时,复位并运行dockershim
。
在其中,启用dockershim.NewDockerService
的功效是:新创建并复位dockershim
服务器端,包含复位docker client、复位cni网络配置等实际操作。
而在其中CNI一部分的关键逻辑性为:
(1)启用cni.ProbeNetworkPlugins
:依据kubelet运行主要参数cni有关配备,获得cni环境变量、cni互联网软件可执行程序等信息内容,依据这种cni的有关信息来复位cniNetworkPlugin
建筑结构并回到;
(2)启用network.InitNetworkPlugin
:依据networkPluginName的值(相匹配kubelet运行主要参数--network-plugin
),挑选相对应的互联网软件,启用其Init()
方式,做互联网软件的复位实际操作(复位实际操作主要是起了一个goroutine,按时检测cni的环境变量及其可执行程序,让其能够 热更新);
(3)将上边流程中获得到的cniNetworkPlugin
建筑结构,取值给dockerService struct
的network
特性,待事后建立pod、删掉pod时能够 启用cniNetworkPlugin
的SetUpPod
、TearDownPod
方式来搭建pod的互联网、消毁pod的互联网。
kubelet对CNI的完成的关键编码:pkg/kubelet/network/cni/cni.go-SetUpPod/TearDownPod
(搭建Pod网络和消毁Pod网络)
在其中涵数入参pluginSettings *NetworkPluginSettings
的变量值,实际上是以kubelet运行参数配置而成,kubelet cni有关运行主要参数在前面早已干了剖析了,忘掉的能够 回过头来再看一下。
// pkg/kubelet/dockershim/docker_service.go
// NewDockerService creates a new `DockerService` struct.
// NOTE: Anything passed to DockerService should be eventually handled in another way when we switch to running the shim as a different process.
func NewDockerService(config *ClientConfig, podSandboxImage string, streamingConfig *streaming.Config, pluginSettings *NetworkPluginSettings,
cgroupsName string, kubeCgroupDriver string, dockershimRootDir string, startLocalStreamingServer bool, noJsonLogPath string) (DockerService, error) {
...
ds := &dockerService{
client: c,
os: kubecontainer.RealOS{},
podSandboxImage: podSandboxImage,
streamingRuntime: &streamingRuntime{
client: client,
execHandler: &NativeExecHandler{},
},
containerManager: cm.NewContainerManager(cgroupsName, client),
checkpointManager: checkpointManager,
startLocalStreamingServer: startLocalStreamingServer,
networkReady: make(map[string]bool),
containerCleanupInfos: make(map[string]*containerCleanupInfo),
noJsonLogPath: noJsonLogPath,
}
...
// dockershim currently only supports CNI plugins.
pluginSettings.PluginBinDirs = cni.SplitDirs(pluginSettings.PluginBinDirString)
// (1)依据kubelet运行主要参数cni有关配备,获得cni环境变量、cni互联网软件可执行程序等信息内容,依据这种cni的有关信息来复位```cniNetworkPlugin```建筑结构并回到
cniPlugins := cni.ProbeNetworkPlugins(pluginSettings.PluginConfDir, pluginSettings.PluginCacheDir, pluginSettings.PluginBinDirs)
cniPlugins = append(cniPlugins, kubenet.NewPlugin(pluginSettings.PluginBinDirs, pluginSettings.PluginCacheDir))
netHost := &dockerNetworkHost{
&namespaceGetter{ds},
&portMappingGetter{ds},
}
// (2)依据networkPluginName的值(相匹配kubelet运行主要参数```--network-plugin```),挑选相对应的互联网软件,启用其```Init()```方式,做互联网软件的复位实际操作(复位实际操作主要是起了一个goroutine,按时检测cni的环境变量及其可执行程序,让其能够 热更新)
plug, err := network.InitNetworkPlugin(cniPlugins, pluginSettings.PluginName, netHost, pluginSettings.HairpinMode, pluginSettings.NonMasqueradeCIDR, pluginSettings.MTU)
if err != nil {
return nil, fmt.Errorf("didn't find compatible CNI plugin with given settings % v: %v", pluginSettings, err)
}
// (3)将上边流程中获得到的```cniNetworkPlugin```建筑结构,取值给```dockerService struct```的```network```特性,待事后建立pod、删掉pod时能够 启用```cniNetworkPlugin```的```SetUpPod```、```TearDownPod```方式来搭建pod的互联网、消毁pod的互联网。 ds.network = network.NewPluginManager(plug)
klog.Infof("Docker cri networking managed by %v", plug.Name())
...
}
先看来下pluginSettings
长什么样,实际上是struct NetworkPluginSettings
,包括了互联网软件名字、互联网软件可执行程序所属文件目录、互联网软件环境变量所属文件目录等特性,编码以下:
// pkg/kubelet/dockershim/docker_service.go
type NetworkPluginSettings struct {
// HairpinMode is best described by comments surrounding the kubelet arg
HairpinMode kubeletconfig.HairpinMode
// NonMasqueradeCIDR is the range of ips which should *not* be included
// in any MASQUERADE rules applied by the plugin
NonMasqueradeCIDR string
// PluginName is the name of the plugin, runtime shim probes for
PluginName string
// PluginBinDirString is a list of directiores delimited by commas, in
// which the binaries for the plugin with PluginName may be found.
PluginBinDirString string
// PluginBinDirs is an array of directories in which the binaries for
// the plugin with PluginName may be found. The admin is responsible for
// provisioning these binaries before-hand.
PluginBinDirs []string
// PluginConfDir is the directory in which the admin places a CNI conf.
// Depending on the plugin, this may be an optional field, eg: kubenet
// generates its own plugin conf.
PluginConfDir string
// PluginCacheDir is the directory in which CNI should store cache files.
PluginCacheDir string
// MTU is the desired MTU for network devices created by the plugin.
MTU int
}
3.1 cni.ProbeNetworkPlugins
cni.ProbeNetworkPlugins中关键功效为:依据kubelet运行主要参数cni有关配备,获得cni环境变量、cni互联网软件可执行程序等信息内容,依据这种cni的有关信息来复位cniNetworkPlugin
建筑结构并回到。
在其中见到plugin.syncNetworkConfig()
启用,关键功效是给cniNetworkPlugin
建筑结构的defaultNetwork
特性取值。
// pkg/kubelet/dockershim/network/cni/cni.go
// ProbeNetworkPlugins : get the network plugin based on cni conf file and bin file
func ProbeNetworkPlugins(confDir, cacheDir string, binDirs []string) []network.NetworkPlugin {
old := binDirs
binDirs = make([]string, 0, len(binDirs))
for _, dir := range old {
if dir != "" {
binDirs = append(binDirs, dir)
}
}
plugin := &cniNetworkPlugin{
defaultNetwork: nil,
loNetwork: getLoNetwork(binDirs),
execer: utilexec.New(),
confDir: confDir,
binDirs: binDirs,
cacheDir: cacheDir,
}
// sync NetworkConfig in best effort during probing.
plugin.syncNetworkConfig()
return []network.NetworkPlugin{plugin}
}
plugin.syncNetworkConfig()
关键逻辑性:
(1)getDefaultCNINetwork()
:依据kubelet运行参数配置,去相匹配的cni conf文件夹名称下找寻cni环境变量,回到包括cni信息的cniNetwork建筑结构;
(2)plugin.setDefaultNetwork()
:依据上一步获得到的cniNetwork建筑结构,取值给cniNetworkPlugin
建筑结构的defaultNetwork
特性。
// pkg/kubelet/dockershim/network/cni/cni.go
func (plugin *cniNetworkPlugin) syncNetworkConfig() {
network, err := getDefaultCNINetwork(plugin.confDir, plugin.binDirs)
if err != nil {
klog.Warningf("Unable to update cni config: %s", err)
return
}
plugin.setDefaultNetwork(network)
}
getDefaultCNINetwork()
关键逻辑性:
(1)在cni环境变量所属文件目录下,能够 鉴别3种cni环境变量,分别是.conf
, .conflist
, .json
。
(2)启用sort.Strings()
将cni环境变量所属文件目录下的全部cni环境变量依照词典次序降序排列。
(3)只留第一个载入到的cni环境变量,随后立即return。因此 即使在cni配备文件名称下配备了好几个cni环境变量,也只能有在其中一个最后起效。
(4)启用cniConfig.ValidateNetworkList()
,校检cni可执行程序文件目录下是不是存有相匹配的可执行程序。
// pkg/kubelet/dockershim/network/cni/cni.go
func getDefaultCNINetwork(confDir string, binDirs []string) (*cniNetwork, error) {
files, err := libcni.ConfFiles(confDir, []string{".conf", ".conflist", ".json"})
switch {
case err != nil:
return nil, err
case len(files) == 0:
return nil, fmt.Errorf("no networks found in %s", confDir)
}
cniConfig := &libcni.CNIConfig{Path: binDirs}
sort.Strings(files)
for _, confFile := range files {
var confList *libcni.NetworkConfigList
if strings.HasSuffix(confFile, ".conflist") {
confList, err = libcni.ConfListFromFile(confFile)
if err != nil {
klog.Warningf("Error loading CNI config list file %s: %v", confFile, err)
continue
}
} else {
conf, err := libcni.ConfFromFile(confFile)
if err != nil {
klog.Warningf("Error loading CNI config file %s: %v", confFile, err)
continue
}
// 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 == "" {
klog.Warningf("Error loading CNI config file %s: no 'type'; perhaps this is a .conflist?", confFile)
continue
}
confList, err = libcni.ConfListFromConf(conf)
if err != nil {
klog.Warningf("Error converting CNI config file %s to list: %v", confFile, err)
continue
}
}
if len(confList.Plugins) == 0 {
klog.Warningf("CNI config list %s has no networks, skipping", string(confList.Bytes[:maxStringLengthInLog(len(confList.Bytes))]))
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 list %s: %v", string(confList.Bytes[:maxStringLengthInLog(len(confList.Bytes))]), err)
continue
}
klog.V(4).Infof("Using CNI configuration file %s", confFile)
return &cniNetwork{
name: confList.Name,
NetworkConfig: confList,
CNIConfig: cniConfig,
Capabilities: caps,
}, nil
}
return nil, fmt.Errorf("no valid networks found in %s", confDir)
}
plugin.setDefaultNetwork
将上边获得到的cniNetwork
结构体赋值给cniNetworkPlugin
建筑结构的defaultNetwork
特性。
// pkg/kubelet/dockershim/network/cni/cni.go
func (plugin *cniNetworkPlugin) setDefaultNetwork(n *cniNetwork) {
plugin.Lock()
defer plugin.Unlock()
plugin.defaultNetwork = n
}
3.2 network.InitNetworkPlugin
network.InitNetworkPlugin()关键功效:依据networkPluginName的值(相匹配kubelet运行主要参数--network-plugin
),挑选相对应的互联网软件,启用其Init()
方式,做互联网软件的复位实际操作。
// pkg/kubelet/dockershim/network/plugins.go
// InitNetworkPlugin inits the plugin that matches networkPluginName. Plugins must have unique names.
func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) (NetworkPlugin, error) {
if networkPluginName == "" {
// default to the no_op plugin
plug := &NoopNetworkPlugin{}
plug.Sysctl = utilsysctl.New()
if err := plug.Init(host, hairpinMode, nonMasqueradeCIDR, mtu); err != nil {
return nil, err
}
return plug, nil
}
pluginMap := map[string]NetworkPlugin{}
allErrs := []error{}
for _, plugin := range plugins {
name := plugin.Name()
if errs := validation.IsQualifiedName(name); len(errs) != 0 {
allErrs = append(allErrs, fmt.Errorf("network plugin has invalid name: %q: %s", name, strings.Join(errs, ";")))
continue
}
if _, found := pluginMap[name]; found {
allErrs = append(allErrs, fmt.Errorf("network plugin %q was registered more than once", name))
continue
}
pluginMap[name] = plugin
}
chosenPlugin := pluginMap[networkPluginName]
if chosenPlugin != nil {
err := chosenPlugin.Init(host, hairpinMode, nonMasqueradeCIDR, mtu)
if err != nil {
allErrs = append(allErrs, fmt.Errorf("network plugin %q failed init: %v", networkPluginName, err))
} else {
klog.V(1).Infof("Loaded network plugin %q", networkPluginName)
}
} else {
allErrs = append(allErrs, fmt.Errorf("network plugin %q not found", networkPluginName))
}
return chosenPlugin, utilerrors.NewAggregate(allErrs)
}
chosenPlugin.Init()
当kubelet运行主要参数--network-plugin
的值配备为cni
时,会启用到cniNetworkPlugin
的Init()
方式,编码以下。
运行一个goroutine,每过5秒,启用一次plugin.syncNetworkConfig
。再去追忆一下plugin.syncNetworkConfig()
的功效:依据kubelet运行参数配置,去相匹配的cni conf文件夹名称下找寻cni环境变量,回到包括cni信息的cniNetwork建筑结构,取值给cniNetworkPlugin
建筑结构的defaultNetwork
特性,进而做到cni conf及其bin升级后,kubelet也可以认知并升级cniNetworkPlugin
建筑结构的实际效果。
这里还可以看得出该goroutine存在的价值,让cni的环境变量及其可执行程序等能够 热更新,而不用重新启动kubelet。
// pkg/kubelet/dockershim/network/cni/cni.go
func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error {
err := plugin.platformInit()
if err != nil {
return err
}
plugin.host = host
plugin.syncNetworkConfig()
// start a goroutine to sync network config from confDir periodically to detect network config updates in every 5 seconds
go wait.Forever(plugin.syncNetworkConfig, defaultSyncConfigPeriod)
return nil
}
plugin.platformInit()仅仅查验了下是不是有nsenter
,沒有做别的实际操作。
// pkg/kubelet/dockershim/network/cni/cni_others.go
func (plugin *cniNetworkPlugin) platformInit() error {
var err error
plugin.nsenterPath, err = plugin.execer.LookPath("nsenter")
if err != nil {
return err
}
return nil
}
4.CNI搭建pod网络剖析
kubelet建立pod时,根据CRI建立并运行pod sandbox,随后CRI会启用CNI互联网软件搭建pod网络。
kubelet中CNI搭建pod网络的方式是:pkg/kubelet/network/cni/cni.go-SetUpPod
。
在其中SetUpPod
方式的启用链以下(只列举了重要一部分):
main (cmd/kubelet/kubelet.go)
…
-> klet.syncPod(pkg/kubelet/kubelet.go)
-> kl.containerRuntime.SyncPod(pkg/kubelet/kubelet.go)
-> m.createPodSandbox(pkg/kubelet/kuberuntime/kuberuntime_manager.go)
-> m.runtimeService.RunPodSandbox (pkg/kubelet/kuberuntime/kuberuntime_sandbox.go)
-> ds.network.SetUpPod(pkg/kubelet/dockershim/docker_sandbox.go)
-> pm.plugin.SetUpPod(pkg/kubelet/dockershim/network/plugins.go)
-> SetUpPod(pkg/kubelet/dockershim/network/cni/cni.go)
下边的编码仅仅列举看来一下重要方式cniNetworkPlugin.SetUpPod()
的启用链,不做深入分析。
// pkg/kubelet/kuberuntime/kuberuntime_manager.go
func (m *kubeGenericRuntimeManager) SyncPod(pod *v1.Pod, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, backOff *flowcontrol.Backoff) (result kubecontainer.PodSyncResult) {
...
podSandboxID, msg, err = m.createPodSandbox(pod, podContainerChanges.Attempt)
...
}
// pkg/kubelet/kuberuntime/kuberuntime_sandbox.go
// createPodSandbox creates a pod sandbox and returns (podSandBoxID, message, error).
func (m *kubeGenericRuntimeManager) createPodSandbox(pod *v1.Pod, attempt uint32) (string, string, error) {
...
podSandBoxID, err := m.runtimeService.RunPodSandbox(podSandboxConfig, runtimeHandler)
...
}
在RunPodSandbox
方式中能够 见到,是先建立pod sandbox,随后运行pod sandbox,随后才算是给该pod sandbox搭建互联网。
// pkg/kubelet/dockershim/docker_sandbox.go
func (ds *dockerService) RunPodSandbox(ctx context.Context, r *runtimeapi.RunPodSandboxRequest) (*runtimeapi.RunPodSandboxResponse, error) {
...
createResp, err := ds.client.CreateContainer(*createConfig)
...
err = ds.client.StartContainer(createResp.ID)
...
err = ds.network.SetUpPod(config.GetMetadata().Namespace, config.GetMetadata().Name, cID, config.Annotations, networkOptions)
...
}
在PluginManager.SetUpPod
方式中能够 见到,启用了pm.plugin.SetUpPod
,前边详细介绍cni复位的情况下讲过有关取值复位实际操作,这儿会启用到cniNetworkPlugin
的SetUpPod
方式。
// pkg/kubelet/dockershim/network/plugins.go
func (pm *PluginManager) SetUpPod(podNamespace, podName string, id kubecontainer.ContainerID, annotations, options map[string]string) error {
defer recordOperation("set_up_pod", time.Now())
fullPodName := kubecontainer.BuildPodFullName(podName, podNamespace)
pm.podLock(fullPodName).Lock()
defer pm.podUnlock(fullPodName)
klog.V(3).Infof("Calling network plugin %s to set up pod %q", pm.plugin.Name(), fullPodName)
if err := pm.plugin.SetUpPod(podNamespace, podName, id, annotations, options); err != nil {
return fmt.Errorf("networkPlugin %s failed to set up pod %q network: %v", pm.plugin.Name(), fullPodName, err)
}
return nil
}
cniNetworkPlugin.SetUpPod
cniNetworkPlugin.SetUpPod方式功效cni互联网软件搭建pod网络的启用通道。其关键逻辑性为:
(1)启用plugin.checkInitialized()
:检查网络软件是不是早已复位进行;
(2)启用plugin.host.GetNetNS()
:获得器皿互联网类名途径,文件格式/proc/${器皿PID}/ns/net
;
(3)启用context.WithTimeout()
:设定启用cni互联网软件的请求超时時间;
(3)启用plugin.addToNetwork()
:如果是linux自然环境,则启用cni互联网软件,给pod搭建环回互联网;
(4)启用plugin.addToNetwork()
:启用cni互联网软件,给pod搭建默认设置 互联网。
// pkg/kubelet/dockershim/network/cni/cni.go
func (plugin *cniNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID, annotations, options map[string]string) error {
if err := plugin.checkInitialized(); err != nil {
return err
}
netnsPath, err := plugin.host.GetNetNS(id.ID)
if err != nil {
return fmt.Errorf("CNI failed to retrieve network namespace path: %v", err)
}
// Todo get the timeout from parent ctx
cniTimeoutCtx, cancelFunc := context.WithTimeout(context.Background(), network.CNITimeoutSec*time.Second)
defer cancelFunc()
// Windows doesn't have loNetwork. It comes only with Linux
if plugin.loNetwork != nil {
if _, err = plugin.addToNetwork(cniTimeoutCtx, plugin.loNetwork, name, namespace, id, netnsPath, annotations, options); err != nil {
return err
}
}
_, err = plugin.addToNetwork(cniTimeoutCtx, plugin.getDefaultNetwork(), name, namespace, id, netnsPath, annotations, options)
return err
}
plugin.addToNetwork
plugin.addToNetwork方式的功效便是启用cni互联网软件,给pod搭建特定种类的互联网,其关键逻辑性为:
(1)启用plugin.buildCNIRuntimeConf():搭建启用cni互联网软件的配备;
(2)启用cniNet.AddNetworkList():启用cni互联网软件,开展互联网搭建。
// pkg/kubelet/dockershim/network/cni/cni.go
func (plugin *cniNetworkPlugin) addToNetwork(ctx context.Context, network *cniNetwork, podName string, podNamespace string, podSandboxID kubecontainer.ContainerID, podNetnsPath string, annotations, options map[string]string) (cnitypes.Result, error) {
rt, err := plugin.buildCNIRuntimeConf(podName, podNamespace, podSandboxID, podNetnsPath, annotations, options)
if err != nil {
klog.Errorf("Error adding network when building cni runtime conf: %v", err)
return nil, err
}
pdesc := podDesc(podNamespace, podName, podSandboxID)
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)
res, err := cniNet.AddNetworkList(ctx, netConf, rt)
if err != nil {
klog.Errorf("Error adding %s to network %s/%s: %v", pdesc, netConf.Plugins[0].Network.Type, netConf.Name, err)
return nil, err
}
klog.V(4).Infof("Added %s to network %s: %v", pdesc, netConf.Name, res)
return res, nil
}
cniNet.AddNetworkList
AddNetworkList方式中主要是启用了addNetwork方式,因此 看来下addNetwork方式的逻辑性:
(1)启用c.exec.FindInPath()
:拼凑出cni互联网软件可执行程序的相对路径;
(2)启用buildOneConfig()
:搭建配备;
(3)启用c.args()
:搭建启用cni互联网软件的主要参数;
(4)启用invoke.ExecPluginWithResult()
:启用cni互联网软件开展pod网络的搭建实际操作。
// vendor/github.com/containernetworking/cni/libcni/api.go
func (c *CNIConfig) AddNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
var err error
var result types.Result
for _, net := range list.Plugins {
result, err = c.addNetwork(ctx, list.Name, list.CNIVersion, net, result, rt)
if err != nil {
return nil, err
}
}
if err = setCachedResult(result, list.Name, rt); err != nil {
return nil, fmt.Errorf("failed to set network %q cached result: %v", list.Name, err)
}
return result, nil
}
func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (types.Result, error) {
c.ensureExec()
pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
if err != nil {
return nil, err
}
newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt)
if err != nil {
return nil, err
}
return invoke.ExecPluginWithResult(ctx, pluginPath, newConf.Bytes, c.args("ADD", rt), c.exec)
}
c.args
c.args方式功效是搭建启用cni互联网软件可执行程序时的主要参数。
从编码中能够 看得出,主要参数有Command
(指令,Add
意味着搭建互联网,Del
意味着消毁互联网)、ContainerID
(器皿ID)、NetNS
(器皿互联网类名途径)、IfName
(Interface Name即网线端口名字)、PluginArgs
(别的主要参数如pod名字、pod类名等)等。
// vendor/github.com/containernetworking/cni/libcni/api.go
func (c *CNIConfig) args(action string, rt *RuntimeConf) *invoke.Args {
return &invoke.Args{
Command: action,
ContainerID: rt.ContainerID,
NetNS: rt.NetNS,
PluginArgs: rt.Args,
IfName: rt.IfName,
Path: strings.Join(c.Path, string(os.PathListSeparator)),
}
}
invoke.ExecPluginWithResult
invoke.ExecPluginWithResult主要是将启用主要参数变为env,随后启用cni互联网软件可执行程序,并获得回到結果。
func ExecPluginWithResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) (types.Result, error) {
if exec == nil {
exec = defaultExec
}
stdoutBytes, err := exec.ExecPlugin(ctx, pluginPath, netconf, args.AsEnv())
if err != nil {
return nil, err
}
// Plugin must return result in same version as specified in netconf
versionDecoder := &version.ConfigDecoder{}
confVersion, err := versionDecoder.Decode(netconf)
if err != nil {
return nil, err
}
return version.NewResult(confVersion, stdoutBytes)
}
5.CNI消毁pod网络剖析
kubelet删掉pod时,CRI会启用CNI互联网软件消毁pod网络。
kubelet中CNI消毁pod网络的方式是:pkg/kubelet/network/cni/cni.go-TearDownPod
。
在其中TearDownPod
方式的启用链以下(只列举了重要一部分):
main (cmd/kubelet/kubelet.go)
…
-> m.runtimeService.StopPodSandbox (pkg/kubelet/kuberuntime/kuberuntime_sandbox.go)
-> ds.network.TearDownPod(pkg/kubelet/dockershim/docker_sandbox.go)
-> pm.plugin.TearDownPod(pkg/kubelet/dockershim/network/plugins.go)
-> TearDownPod(pkg/kubelet/dockershim/network/cni/cni.go)
下边的编码仅仅列举看来一下重要方式cniNetworkPlugin.TearDownPod()
的启用链,不做深入分析。
在StopPodSandbox
方式中能够 见到,会先消毁pod网络,随后终止pod sandbox的运作,可是这两个实际操作中的一切一个产生不正确,kubelet都是会再次开展再试,直至取得成功截止,因此 对这两个提交成功的次序并沒有严苛的规定(删掉pod sandbox的实际操作由kubelet gc去进行)。
// pkg/kubelet/dockershim/docker_sandbox.go
func (ds *dockerService) StopPodSandbox(ctx context.Context, r *runtimeapi.StopPodSandboxRequest) (*runtimeapi.StopPodSandboxResponse, error) {
...
// WARNING: The following operations made the following assumption:
// 1. kubelet will retry on any error returned by StopPodSandbox.
// 2. tearing down network and stopping sandbox container can succeed in any sequence.
// This depends on the implementation detail of network plugin and proper error handling.
// For kubenet, if tearing down network failed and sandbox container is stopped, kubelet
// will retry. On retry, kubenet will not be able to retrieve network namespace of the sandbox
// since it is stopped. With empty network namespcae, CNI bridge plugin will conduct best
// effort clean up and will not return error.
errList := []error{}
ready, ok := ds.getNetworkReady(podSandboxID)
if !hostNetwork && (ready || !ok) {
// Only tear down the pod network if we haven't done so already
cID := kubecontainer.BuildContainerID(runtimeName, podSandboxID)
err := ds.network.TearDownPod(namespace, name, cID)
if err == nil {
ds.setNetworkReady(podSandboxID, false)
} else {
errList = append(errList, err)
}
}
if err := ds.client.StopContainer(podSandboxID, defaultSandboxGracePeriod); err != nil {
// Do not return error if the container does not exist
if !libdocker.IsContainerNotFoundError(err) {
klog.Errorf("Failed to stop sandbox %q: %v", podSandboxID, err)
errList = append(errList, err)
} else {
// remove the checkpoint for any sandbox that is not found in the runtime
ds.checkpointManager.RemoveCheckpoint(podSandboxID)
}
}
...
}
在PluginManager.TearDownPod
方式中能够 见到,启用了pm.plugin.TearDownPod
,前边详细介绍cni复位的情况下讲过有关取值复位实际操作,这儿会启用到cniNetworkPlugin
的TearDownPod
方式。
// pkg/kubelet/dockershim/network/plugins.go
func (pm *PluginManager) TearDownPod(podNamespace, podName string, id kubecontainer.ContainerID) error {
defer recordOperation("tear_down_pod", time.Now())
fullPodName := kubecontainer.BuildPodFullName(podName, podNamespace)
pm.podLock(fullPodName).Lock()
defer pm.podUnlock(fullPodName)
klog.V(3).Infof("Calling network plugin %s to tear down pod %q", pm.plugin.Name(), fullPodName)
if err := pm.plugin.TearDownPod(podNamespace, podName, id); err != nil {
return fmt.Errorf("networkPlugin %s failed to teardown pod %q network: %v", pm.plugin.Name(), fullPodName, err)
}
return nil
}
cniNetworkPlugin.TearDownPod
cniNetworkPlugin.TearDownPod方式功效cni互联网软件消毁pod网络的启用通道。其关键逻辑性为:
(1)启用plugin.checkInitialized()
:检查网络软件是不是早已复位进行;
(2)启用plugin.host.GetNetNS()
:获得器皿互联网类名途径,文件格式/proc/${器皿PID}/ns/net
;
(3)启用context.WithTimeout()
:设定启用cni互联网软件的请求超时時间;
(3)启用plugin.deleteFromNetwork()
:如果是linux自然环境,则启用cni互联网软件,消毁pod的环回互联网;
(4)启用plugin.deleteFromNetwork()
:启用cni互联网软件,消毁pod的默认设置 互联网。
// pkg/kubelet/dockershim/network/cni/cni.go
func (plugin *cniNetworkPlugin) TearDownPod(namespace string, name string, id kubecontainer.ContainerID) error {
if err := plugin.checkInitialized(); err != nil {
return err
}
// Lack of namespace should not be fatal on teardown
netnsPath, err := plugin.host.GetNetNS(id.ID)
if err != nil {
klog.Warningf("CNI failed to retrieve network namespace path: %v", err)
}
// Todo get the timeout from parent ctx
cniTimeoutCtx, cancelFunc := context.WithTimeout(context.Background(), network.CNITimeoutSec*time.Second)
defer cancelFunc()
// Windows doesn't have loNetwork. It comes only with Linux
if plugin.loNetwork != nil {
// Loopback network deletion failure should not be fatal on teardown
if err := plugin.deleteFromNetwork(cniTimeoutCtx, plugin.loNetwork, name, namespace, id, netnsPath, nil); err != nil {
klog.Warningf("CNI failed to delete loopback network: %v", err)
}
}
return plugin.deleteFromNetwork(cniTimeoutCtx, plugin.getDefaultNetwork(), name, namespace, id, netnsPath, nil)
}
plugin.deleteFromNetwork
plugin.deleteFromNetwork方式的功效便是启用cni互联网软件,消毁pod特定种类的互联网,其关键逻辑性为:
(1)启用plugin.buildCNIRuntimeConf():搭建启用cni互联网软件的配备;
(2)启用cniNet.DelNetworkList():启用cni互联网软件,开展pod网络消毁。
// pkg/kubelet/dockershim/network/cni/cni.go
func (plugin *cniNetworkPlugin) deleteFromNetwork(ctx context.Context, network *cniNetwork, podName string, podNamespace string, podSandboxID kubecontainer.ContainerID, podNetnsPath string, annotations map[string]string) error {
rt, err := plugin.buildCNIRuntimeConf(podName, podNamespace, podSandboxID, podNetnsPath, annotations, nil)
if err != nil {
klog.Errorf("Error deleting network when building cni runtime conf: %v", err)
return err
}
pdesc := podDesc(podNamespace, podName, podSandboxID)
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)
err = cniNet.DelNetworkList(ctx, netConf, rt)
// 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.
if err != nil && !strings.Contains(err.Error(), "no such file or directory") {
klog.Errorf("Error deleting %s from network %s/%s: %v", pdesc, netConf.Plugins[0].Network.Type, netConf.Name, err)
return err
}
klog.V(4).Infof("Deleted %s from network %s/%s", pdesc, netConf.Plugins[0].Network.Type, netConf.Name)
return nil
}
cniNet.DelNetworkList
DelNetworkList方式中主要是启用了addNetwork方式,因此 看来下addNetwork方式的逻辑性:
(1)启用c.exec.FindInPath()
:拼凑出cni互联网软件可执行程序的相对路径;
(2)启用buildOneConfig()
:搭建配备;
(3)启用c.args()
:搭建启用cni互联网软件的主要参数;
(4)启用invoke.ExecPluginWithResult()
:启用cni互联网软件开展pod网络的消毁实际操作。
// vendor/github.com/containernetworking/cni/libcni/api.go
// DelNetworkList executes a sequence of plugins with the DEL command
func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) error {
var cachedResult types.Result
// Cached result on DEL was added in CNI spec version 0.4.0 and higher
if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil {
return err
} else if gtet {
cachedResult, err = getCachedResult(list.Name, list.CNIVersion, rt)
if err != nil {
return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
}
}
for i := len(list.Plugins) - 1; i >= 0; i-- {
net := list.Plugins[i]
if err := c.delNetwork(ctx, list.Name, list.CNIVersion, net, cachedResult, rt); err != nil {
return err
}
}
_ = delCachedResult(list.Name, rt)
return nil
}
func (c *CNIConfig) delNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) error {
c.ensureExec()
pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
if err != nil {
return err
}
newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt)
if err != nil {
return err
}
return invoke.ExecPluginWithoutResult(ctx, pluginPath, newConf.Bytes, c.args("DEL", rt), c.exec)
}
c.args
c.args方式功效是搭建启用cni互联网软件可执行程序时的主要参数。
从编码中能够 看得出,主要参数有Command
(指令,Add
意味着搭建互联网,Del
意味着消毁互联网)、ContainerID
(器皿ID)、NetNS
(器皿互联网类名途径)、IfName
(Interface Name即网线端口名字)、PluginArgs
(别的主要参数如pod名字、pod类名等)等。
// vendor/github.com/containernetworking/cni/libcni/api.go
func (c *CNIConfig) args(action string, rt *RuntimeConf) *invoke.Args {
return &invoke.Args{
Command: action,
ContainerID: rt.ContainerID,
NetNS: rt.NetNS,
PluginArgs: rt.Args,
IfName: rt.IfName,
Path: strings.Join(c.Path, string(os.PathListSeparator)),
}
}
invoke.ExecPluginWithResult
invoke.ExecPluginWithResult主要是将启用主要参数变为env,随后启用cni互联网软件可执行程序,并获得回到結果。
func ExecPluginWithResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) (types.Result, error) {
if exec == nil {
exec = defaultExec
}
stdoutBytes, err := exec.ExecPlugin(ctx, pluginPath, netconf, args.AsEnv())
if err != nil {
return nil, err
}
// Plugin must return result in same version as specified in netconf
versionDecoder := &version.ConfigDecoder{}
confVersion, err := versionDecoder.Decode(netconf)
if err != nil {
return nil, err
}
return version.NewResult(confVersion, stdoutBytes)
}
汇总
CNI
CNI,全名是 Container Network Interface,即器皿网线端口。
CNI是K8s 中规范的启用互联网完成的插口。Kubelet 根据这一规范的插口来启用不一样的互联网软件以完成不一样的网络配置方法。
CNI互联网软件是一个可执行程序,是遵循器皿网线端口(CNI)标准的互联网软件。普遍的 CNI互联网软件包含 Calico、flannel、Terway、Weave Net等。
当kubelet挑选应用CNI种类的互联网软件时(根据kubelet运行主要参数特定),kubelet在建立pod、删掉pod的情况下,根据CRI启用CNI互联网软件来做pod的搭建互联网和消毁互联网等实际操作。
kubelet搭建pod网络的大概全过程
(1)kubelet先根据CRI建立pause器皿(pod sandbox),转化成network namespace;
(2)kubelet依据运行参数配置启用实际的互联网软件如CNI互联网软件;
(3)互联网软件给pause器皿(pod sandbox)配备互联网;
(4)pod 中别的的器皿都和pause器皿(pod sandbox)分享网络。
kubelet部件CNI有关运行主要参数剖析
(1)--network-plugin
:特定要应用的互联网软件种类,可选值cni
、kubenet
、""
,默认设置 为空串,意味着Noop,即不配备互联网软件(不搭建pod网络)。这里配备数值cni
时,即特定kubelet应用的互联网软件种类为cni
。
(2)--cni-conf-dir
:CNI 环境变量所属途径。初始值:/etc/cni/net.d
。
(3)--cni-bin-dir
:CNI 软件的可执行程序所属途径,kubelet 将在这里途径中搜索 CNI 软件的可执行程序来实行pod的互联网实际操作。初始值:/opt/cni/bin
。
kubelet中的CNI复位
kubelet运行后,会依据运行主要参数中cni的有关主要参数,获得cni环境变量并复位cni互联网软件,待事后建立pod、删掉pod的时候会启用SetUpPod
、TearDownPod
方式来搭建pod的互联网、消毁pod的互联网。与此同时,复位时起了一个goroutine,按时检测cni的环境变量及其可执行程序,让其能够 热更新。
CNI搭建pod网络
kubelet建立pod时,根据CRI建立并运行pod sandbox,随后CRI会启用CNI互联网软件搭建pod网络。
kubelet中CNI搭建pod网络的编码方式是:pkg/kubelet/network/cni/cni.go-SetUpPod
。
CNI消毁pod网络
kubelet删掉pod时,CRI会启用CNI互联网软件消毁pod网络。
kubelet中CNI消毁pod网络的方式是:pkg/kubelet/network/cni/cni.go-TearDownPod
。
关注不迷路
扫码下方二维码,关注宇凡盒子公众号,免费获取最新技术内幕!
评论0