温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

kubernetes的CNI怎么安装

发布时间:2022-01-12 10:07:06 来源:亿速云 阅读:701 作者:iii 栏目:云计算

今天小编给大家分享一下kubernetes的CNI怎么安装的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

环境介绍

我们安装kubernetes时先不安装CNI. 如果使用了sealyun离线包 那么修改下 kube/conf/master.sh

只留如下内容即可:

[root@helix105 shell]# cat master.sh  kubeadm init --config ../conf/kubeadm.yaml mkdir ~/.kube cp /etc/kubernetes/admin.conf ~/.kube/config kubectl taint nodes --all node-role.kubernetes.io/master-

清空CNI相关目录:

rm -rf /opt/cni/bin/* rm -rf /etc/cni/net.d/*

启动kubernetes, 如果已经装过那么kubeadm reset一下:

cd kube/shell && sh init.sh && sh master.sh

此时你的节点是notready的,你的coredns也没有办法分配到地址:

[root@helix105 shell]# kubectl get pod -n kube-system -o wide NAME                                            READY   STATUS    RESTARTS   AGE   IP              NODE                    NOMINATED NODE   READINESS GATES coredns-5c98db65d4-5fh7c                        0/1     Pending   0          54s   <none>          <none>                  <none>           <none> coredns-5c98db65d4-dbwmq                        0/1     Pending   0          54s   <none>          <none>                  <none>           <none> kube-controller-manager-helix105.hfa.chenqian   1/1     Running   0          19s   172.16.60.105   helix105.hfa.chenqian   <none>           <none> kube-proxy-k74ld                                1/1     Running   0          54s   172.16.60.105   helix105.hfa.chenqian   <none>           <none> kube-scheduler-helix105.hfa.chenqian            1/1     Running   0          14s   172.16.60.105   helix105.hfa.chenqian   <none>           <none> [root@helix105 shell]# kubectl get node NAME                    STATUS     ROLES    AGE   VERSION helix105.hfa.chenqian   NotReady   master   86s   v1.15.0

安装CNI

创建CNI配置文件

$ mkdir -p /etc/cni/net.d $ cat >/etc/cni/net.d/10-mynet.conf <<EOF {	"cniVersion": "0.2.0",	"name": "mynet",	"type": "bridge",	"bridge": "cni0",	"isGateway": true,	"ipMasq": true,	"ipam": {	"type": "host-local",	"subnet": "10.22.0.0/16",	"routes": [	{ "dst": "0.0.0.0/0" }	]	} } EOF $ cat >/etc/cni/net.d/99-loopback.conf <<EOF {	"cniVersion": "0.2.0",	"name": "lo",	"type": "loopback" } EOF

这里两个配置一个是给容器塞一个网卡挂在网桥上的,另外一个配置负责撸(本地回环)。。

配置完后会发现节点ready:

[root@helix105 shell]# kubectl get node NAME                    STATUS   ROLES    AGE   VERSION helix105.hfa.chenqian   Ready    master   15m   v1.15.0

但是coredns会一直处于ContainerCreating状态,是因为bin文件还没有:

failed to find plugin "bridge" in path [/opt/cni/bin]

plugins里实现了很多的CNI,如我们上面配置的bridge.

$ cd $GOPATH/src/github.com/containernetworking/plugins $ ./build_linux.sh $ cp bin/* /opt/cni/bin $ ls bin/ bandwidth  dhcp      flannel      host-local  loopback  portmap  sbr     tuning bridge     firewall  host-device  ipvlan      macvlan   ptp      static  vlan

这里有很多二进制,我们学习的话不需要关注所有的,就看ptp(就简单的创建了设备对)或者bridge

再看coredns已经能分配到地址了:

[root@helix105 plugins]# kubectl get pod -n kube-system -o wide NAME                                            READY   STATUS    RESTARTS   AGE     IP              NODE                    NOMINATED NODE   READINESS GATES coredns-5c98db65d4-5fh7c                        1/1     Running   0          3h20m   10.22.0.8       helix105.hfa.chenqian   <none>           <none> coredns-5c98db65d4-dbwmq                        1/1     Running   0          3h20m   10.22.0.9

看一下网桥,cni0上挂了两个设备,与我们上面的cni配置里配置的一样,type字段指定用哪个bin文件,bridge字段指定网桥名:

[root@helix105 plugins]# brctl show bridge name	bridge id	STP enabled	interfaces cni0	8000.8ef6ac49c2f7	no	veth2b28b06f             	veth2c093940

原理

为了更好理解kubelet干嘛了,我们可以找一个脚本来解释 script 这个脚本也可以用来测试你的CNI:

为了易读,我删除一些不重要的东西,原版脚本可以在连接中去拿

# 先创建一个容器,这里只为了拿到一个net namespace contid=$(docker run -d --net=none golang:1.12.7 /bin/sleep 10000000)  pid=$(docker inspect -f '{{ .State.Pid }}' $contid) netnspath=/proc/$pid/ns/net # 这个我们需要 kubelet启动pod时也是创建好容器就有了pod的network namespaces,再去把ns传给cni 让cni去配置 ./exec-plugins.sh add $contid $netnspath # 传入两个参数给下一个脚本,containerid和net namespace路径 docker run --net=container:$contid $@
NETCONFPATH=${NETCONFPATH-/etc/cni/net.d} i=0 # 获取容器id和网络ns contid=$2  netns=$3 # 这里设置了几个环境变量,CNI命令行工具就可以获取到这些参数 export CNI_COMMAND=$(echo $1 | tr '[:lower:]' '[:upper:]') export PATH=$CNI_PATH:$PATH # 这个指定CNI bin文件的路径 export CNI_CONTAINERID=$contid  export CNI_NETNS=$netns for netconf in $(echo $NETCONFPATH/10-mynet.conf | sort); do         name=$(jq -r '.name' <$netconf)         plugin=$(jq -r '.type' <$netconf) # CNI配置文件的type字段对应二进制程序名         export CNI_IFNAME=$(printf eth%d $i) # 容器内网卡名         # 这里执行了命令行工具         res=$($plugin <$netconf) # 这里把CNI的配置文件通过标准输入也传给CNI命令行工具         if [ $? -ne 0 ]; then                 # 把结果输出到标准输出,这样kubelet就可以拿到容器地址等一些信息                 errmsg=$(echo $res | jq -r '.msg')                 if [ -z "$errmsg" ]; then                         errmsg=$res                 fi                 echo "${name} : error executing $CNI_COMMAND: $errmsg"                 exit 1         let "i=i+1" done

总结一下:

         CNI配置文件          容器ID          网络ns kubelet -------------->  CNI command    ^                        |    |                        |    +------------------------+        结果标准输出

bridge CNI实现

既然这么简单,那么就可以去看看实现了:

bridge CNI代码

//cmdAdd 负责创建网络 func cmdAdd(args *skel.CmdArgs) error  //入参数都已经写到这里面了,前面的参数从环境变量读取的,CNI配置从stdin读取的 type CmdArgs struct {	ContainerID string	Netns       string	IfName      string	Args        string	Path        string	StdinData   []byte }

所以CNI配置文件除了name type这些特定字段,你自己也可以加自己的一些字段.然后自己去解析

然后啥事都得靠自己了

//这里创建了设备对,并挂载到cni0王桥上 hostInterface, containerInterface, err := setupVeth(netns, br, args.IfName, n.MTU, n.HairpinMode, n.Vlan)

具体怎么挂的就是调用了netlink 这个库,sealos在做内核负载时同样用了该库。

err := netns.Do(func(hostNS ns.NetNS) error { //创建设备对	hostVeth, containerVeth, err := ip.SetupVeth(ifName, mtu, hostNS)     ...     //配置容器内的网卡名mac地址等	contIface.Name = containerVeth.Name	contIface.Mac = containerVeth.HardwareAddr.String()	contIface.Sandbox = netns.Path()	hostIface.Name = hostVeth.Name	return nil }) ... // 根据index找到宿主机设备对名 hostVeth, err := netlink.LinkByName(hostIface.Name) ... hostIface.Mac = hostVeth.Attrs().HardwareAddr.String() // 把宿主机端设备对挂给网桥 if err := netlink.LinkSetMaster(hostVeth, br); err != nil {} // 设置hairpin mode if err = netlink.LinkSetHairpin(hostVeth, hairpinMode); err != nil { } // 设置vlanid if vlanID != 0 {	err = netlink.BridgeVlanAdd(hostVeth, uint16(vlanID), true, true, false, true) } return hostIface, contIface, nil

最后把结果返回:

type Result struct {	CNIVersion string         `json:"cniVersion,omitempty"`	Interfaces []*Interface   `json:"interfaces,omitempty"`	IPs        []*IPConfig    `json:"ips,omitempty"`	Routes     []*types.Route `json:"routes,omitempty"`	DNS        types.DNS      `json:"dns,omitempty"` } // 这样kubelet就收到返回信息了 func (r *Result) PrintTo(writer io.Writer) error {	data, err := json.MarshalIndent(r, "", "    ")	if err != nil {	return err	}	_, err = writer.Write(data)	return err }

如:

{   "cniVersion": "0.4.0",   "interfaces": [                                            (this key omitted by IPAM plugins)       {           "name": "<name>",           "mac": "<MAC address>",                            (required if L2 addresses are meaningful)           "sandbox": "<netns path or hypervisor identifier>" (required for container/hypervisor interfaces, empty/omitted for host interfaces)       }   ],   "ips": [       {           "version": "<4-or-6>",           "address": "<ip-and-prefix-in-CIDR>",           "gateway": "<ip-address-of-the-gateway>",          (optional)           "interface": <numeric index into 'interfaces' list>       },       ...   ],   "routes": [                                                (optional)       {           "dst": "<ip-and-prefix-in-cidr>",           "gw": "<ip-of-next-hop>"                           (optional)       },       ...   ],   "dns": {                                                   (optional)     "nameservers": <list-of-nameservers>                     (optional)     "domain": <name-of-local-domain>                         (optional)     "search": <list-of-additional-search-domains>            (optional)     "options": <list-of-options>                             (optional)   } }

以上就是“kubernetes的CNI怎么安装”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI