所有文章

k8s CNI

CNI(container network interface)

为了将网络功能插件化,k8s要1.5提出了CNI标准,现在我们常用的网络如:flannel、calico等都是基于CNI标准开发的。

kubelet配置CNI

--network-plugin=cni
--cni-bin-dir=/opt/cni/bin
--cni-conf-dir=/etc/cni/net.d

接口定义

vendor/github.com/containernetworking/cni/libcni/api.go

type CNI interface {
	AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
	DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error

	AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
	DelNetwork(net *NetworkConfig, rt *RuntimeConf) error
}

接口实现

下面以calico-plugin为例说明CNI的实现,calico-plugin与calico容器网络之间没有直接关系,我们通常说的calico指的是这两个东西的组合,而calico容器网络是解决不同物理机上容器之间的通信,而calico-plugin是在k8s创建Pod时为Pod设置虚拟网卡,也就是容器中的eth0lo网卡,calico-plugin是由两个静态的二进制文件组成,由kubelet以命令行的形式调用,这两个二进制的作用如下:

文件在物理机上的位置:

/opt/cni/
├── bin
│   ├── calico
│   ├── calico-ipam
└── net.d
    └── 10-calico.conf

calico-plugin在ETCD中维护的信息:

curl -s localhost:2379/v2/keys/calico/ipam/v2/assignment/ipv4/block | jq

calico插件配置

vim /opt/cni/net.d/10-calico.conf
{
    "name": "calico-k8s-network",
    "cniVersion": "0.1.0",
    "type": "calico",
    "etcd_endpoints": "http://127.0.0.1:2379",
    "log_level": "info",
    "ipam": {
        "type": "calico-ipam"
    },
    "kubernetes": {
        "kubeconfig": "/opt/rainbond/kubernetes/kubecfg/admin.kubeconfig"
    }
}

calico-plugin工作原理

kubelet在创建一个Pod时,会先启动puase容器,然后为这个容器添加设置网络,也就是添加网卡,这里会通过CNI调起文件系统中的/opt/cni/bin/calico,并将Pod信息通过标准输入(stdin)传递给calico进程,calico通过修改系统中Namespace达到为容器添加网卡的目的。

calico-plugin源码分析

/opt/cni/bin/calico的入口函数定义在calico.go文件中,这个文件中有三个主要函数:

我们看cmdAdd()函数的实现,cmdAdd()是个通用函数,它会根据wepIDs.Orchestrator字段的值调用calico针对k8s的实现:calico.go:190

if wepIDs.Orchestrator == api.OrchestratorKubernetes {
    if result, err = k8s.CmdAddK8s(ctx, args, conf, *wepIDs, calicoClient, endpoint); err != nil {
        return err
    }

其中k8s.CmdAddK8s()函数的主要工作如下:

相关资料


编写日期:2018-07-21