$ ls /opt/cni/bin/
bandwidth bridge dhcp firewall flannel host-device host-local ipvlan loopback macvlan portmap ptp sbr static tuning vlan
# CNI_COMMAND=ADD 顾名思义表示创建。
# XXX=XXX 其他参数定义见下文。
# < config.json 表示从标准输入传递配置文件
CNI_COMMAND=ADD XXX=XXX ./bridge < config.json
-
CNI_COMMAND:定义期望的操作,可以是ADD,DEL,CHECK或VERSION。
-
CNI_CONTAINERID:容器ID,由容器运行时管理的容器唯一标识符。
-
CNI_NETNS:容器网络命名空间的路径。(形如 /run/netns/[nsname])。
-
CNI_IFNAME:需要被创建的网络接口名称,例如eth0。
-
CNI_ARGS:运行时调用时传入的额外参数,格式为分号分隔的key-value对,例如FOO=BAR;ABC=123
-
CNI_PATH:CNI插件可执行文件的路径,例如/opt/cni/bin。
{
"cniVersion": "0.4.0", // 表示希望插件遵循的CNI标准的版本。
"name": "dbnet", // 表示网络名称。这个名称并非指网络接口名称,是便于CNI管理的一个表示。应当在当前主机(或其他管理域)上全局唯一。
"type": "bridge", // 插件类型
"bridge": "cni0", // Bridge插件的参数,指定网桥名称。
"ipam": { // IP Allocation Management,管理IP地址分配。
"type": "host-local", // IPAM插件的类型。
// IPAM定义的参数
"subnet": "10.1.0.0/16",
"gateway": "10.1.0.1"
}
}
type NetworkConfig struct {
Network *types.NetConf
Bytes []byte
}
...
// NetConf describes a network.
type NetConf struct {
CNIVersion string `json:"cniVersion,omitempty"`
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Capabilities map[string]bool `json:"capabilities,omitempty"`
IPAM IPAM `json:"ipam,omitempty"`
DNS DNS `json:"dns"`
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
PrevResult Result `json:"-"`
}
-
cniVersion:表示希望插件遵循的CNI标准的版本。
-
name:表示网络名称。这个名称并非指网络接口名称,是便于CNI管理的一个表示。应当在当前主机(或其他管理域)上全局唯一。
-
type:表示插件的名称,也就是插件对应的可执行文件的名称。
-
Bridge:该参数属于bridge插件的参数,指定主机网桥的名称。
-
IPAM:表示IP地址分配插件的配置,ipam.type则表示IPAM的插件类型。
type NetConf struct {
types.NetConf // <-- 嵌入公共部分
// 底下的都是插件定义部分
BrName string `json:"bridge"`
IsGW bool `json:"isGateway"`
IsDefaultGW bool `json:"isDefaultGateway"`
ForceAddress bool `json:"forceAddress"`
IPMasq bool `json:"ipMasq"`
MTU int `json:"mtu"`
HairpinMode bool `json:"hairpinMode"`
PromiscMode bool `json:"promiscMode"`
Vlan int `json:"vlan"`
Args struct {
Cni BridgeArgs `json:"cni,omitempty"`
} `json:"args,omitempty"`
RuntimeConfig struct {
Mac string `json:"mac,omitempty"`
} `json:"runtimeConfig,omitempty"`
mac string
}
-
为容器所在的网络命名空间创建一个网络接口,或者
-
修改容器所在网络命名空间中的指定网络接口
-
为容器所在的网络命名空间删除一个网络接口,或者
-
撤销ADD操作的修改
$ CNI_COMMAND=VERSION /opt/cni/bin/bridge
{"cniVersion":"0.4.0","supportedVersions":["0.1.0","0.2.0","0.3.0","0.3.1","0.4.0"]}
{
"cniVersion": "0.4.0",
"name": "dbnet",
"plugins": [
{
"type": "bridge",
// type (plugin) specific
"bridge": "cni0"
},
"ipam": {
"type": "host-local",
// ipam specific
"subnet": "10.1.0.0/16",
"gateway": "10.1.0.1"
}
},
{
"type": "tuning",
"sysctl": {
"net.core.somaxconn": "500"
}
}
]
}
type NetworkConfigList struct {
Name string
CNIVersion string
DisableCheck bool
Plugins []*NetworkConfig
Bytes []byte
}
{
"cniVersion": "0.4.0",
"name": "dbnet",
"type": "bridge",
"bridge": "cni0",
"ipam": {
"type": "host-local",
"subnet": "10.1.0.0/16",
"gateway": "10.1.0.1"
}
}
{
"cniVersion": "0.4.0",
"name": "dbnet",
"type": "tuning",
"sysctl": {
"net.core.somaxconn": "500"
},
"prevResult": { // 调用Bridge插件的返回结果
...
}
}
wget https://github.com/containernetworking/plugins/releases/download/v0.9.1/cni-plugins-linux-amd64-v0.9.1.tgz
mkdir -p ~/cni/bin
tar zxvf cni-plugins-linux-amd64-v0.9.1.tgz -C ./cni/bin
chmod x ~/cni/bin/*
ls ~/cni/bin/
bandwidth bridge dhcp firewall flannel host-device host-local ipvlan loopback macvlan portmap ptp sbr static tuning vlan vrfz
contid=$(docker run -d --net=none --name nginx nginx) # 容器ID
pid=$(docker inspect -f '{{ .State.Pid }}' $contid) # 容器进程ID
netnspath=/proc/$pid/ns/net # 命名空间路径
nsenter -t $pid -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
{
"cniVersion": "0.4.0",
"name": "mynet",
"type": "bridge",
"bridge": "mynet0",
"isDefaultGateway": true,
"forceAddress": false,
"ipMasq": true,
"hairpinMode": true,
"ipam": {
"type": "host-local",
"subnet": "10.10.0.0/16"
}
}
CNI_COMMAND=ADD CNI_CONTAINERID=$contid CNI_NETNS=$netnspath CNI_IFNAME=eth0 CNI_PATH=~/cni/bin ~/cni/bin/bridge < bridge.json
{
"cniVersion": "0.4.0",
"interfaces": [
....
],
"ips": [
{
"version": "4",
"interface": 2,
"address": "10.10.0.2/16", //给容器分配的IP地址
"gateway": "10.10.0.1"
}
],
"routes": [
.....
],
"dns": {}
}
nsenter -t $pid -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
5: eth0@if40: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether c2:8f:ea:1b:7f:85 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.10.0.2/16 brd 10.10.255.255 scope global eth0
valid_lft forever preferred_lft forever
ls /var/lib/cni/networks/mynet/
10.10.0.2 last_reserved_ip.0 lock
ip route add 10.10.0.0/16 dev mynet0 src 10.10.0.1 # 添加路由
curl -I 10.10.0.2 # IP换成实际分配给容器的IP地址
HTTP/1.1 200 OK
....
CNI_COMMAND=DEL CNI_CONTAINERID=$contid CNI_NETNS=$netnspath CNI_IFNAME=eth0 CNI_PATH=~/cni/bin ~/cni/bin/bridge < bridge.json
go install github.com/containernetworking/cni/cnitool@latest
{
"cniVersion": "0.4.0",
"name": "portmap",
"plugins": [
{
"type": "bridge",
"bridge": "mynet0",
"isDefaultGateway": true,
"forceAddress": false,
"ipMasq": true,
"hairpinMode": true,
"ipam": {
"type": "host-local",
"subnet": "10.10.0.0/16",
"gateway": "10.10.0.1"
}
},
{
"type": "portmap",
"runtimeConfig": {
"portMappings": [
{"hostPort": 8080, "containerPort": 80, "protocol": "tcp"}
]
}
}
]
}
-
NETCONFPATH:指定配置文件(*.conflist)的所在路径,默认路径为/etc/cni/net.d
-
CNI_PATH:指定CNI插件的存放路径。
CNI_PATH=~/cni/bin NETCONFPATH=. cnitool add portmap $netnspath
CNI_PATH=~/cni/bin NETCONFPATH=. cnitool del portmap $netnspath
-
通过JSON配置文件定义网络配置;
-
通过调用可执行程序(CNI插件)来对容器网络执行配置;
-
通过链式调用的方式来支持多插件的组合使用。
-
https://github.com/containernetworking/cni/blob/spec-v0.4.0/SPEC.md
-
https://github.com/containernetworking/cni/blob/master/SPEC.md
-
https://www.cni.dev/plugins/current/
-
https://github.com/containernetworking/cni/tree/master/cnitool
-
https://kubernetes.io/blog/2016/01/why-kubernetes-doesnt-use-libnetwork/
-
https://www.youtube.com/watch?v=YWXucnygGmY
-
https://www.youtube.com/watch?v=0tbnXX7jXdg
本文始发于微信公众号(分布式实验室):深入理解CNI(容器网络接口)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论