CNCF CNI系列之二:CNI(container network interface)概览(以macvlan为例)

本文介绍了CNCF的CNI接口规范及其应用,详细解析了CNI接口支持的操作、设计考量及环境变量参数等内容,并通过手动配置和调用macvlan CNI插件的实际案例,展示了如何实现容器网络配置。

一、前言

CNCF的CNI是一个接口规范,这个规范定义了输入、输出的标准和调用的接口。只要调用CNI插件的实体遵守这个规范,就能从CNI拿到满足网络互通条件的网络参数(如IP地址、网关、路由、DNS等),这些网络参数可以配置container实例。

本文通过分析手动调用macvlan CNI的过程,了解CNI接口规范的运行模式。

转载自https://blog.youkuaiyun.com/cloudvtech

二、container宿主机配置

所在网段:192.168.122.0/24

网卡配置:

 eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 52:54:00:d8:d2:1e brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.135/24 brd 192.168.122.255 scope global dynamic eth0
       valid_lft 2355sec preferred_lft 2355sec
    inet6 fe80::5054:ff:fed8:d21e/64 scope link
       valid_lft forever preferred_lft forever 

转载自https://blog.youkuaiyun.com/cloudvtech

三、CNI接口规范

1. CNI接口支持的调用法方

添加网络、删除网络、添加网络列表、删除网络列表。

CNI plugin的功能可以概括为将container加入网络并被container的网络接口配置网络信息。

2. CNI插件

CNI插件必须是一个可执行文件。CNI插件负责将网络接口(比如veth的一端)插入container network namespace里面,并在主机上进行link level(比如veth的另一端)配置,使得container的在link level能够联通到主机。然后,CNI将IP配置给网络接口并设置相关路由。

3. 设计考量

CNI设计的时候考虑了以下问题(https://github.com/containernetworking/cni/blob/master/SPEC.md, "General considerations"):
  • CRT(container run time)必须在调用CNI plugin之前为容器创建一个network namespace。
  • CRI必须确定这个container应属于哪个网络,并为每个网络确定哪些插件必须被执行。
  • 网络配置采用JSON格式。网络配置包括必填字段,如name和type以及插件(类型)。网络配置允许不同的CNI plugin有一部分自定义的参数,为此,有一个可选的字段args,可以包含特定CNI plugin所需的不同的信息。
  • CRI必须按顺序为每个网络执行相应的CNI plugin,将container添加到每个网络中。
  • 在完成container生命周期后,运行时必须以相反的顺序执行插件(相对于执行添加container的顺序)以将container与网络断开连接。
  • CRI关注CNI plugin的ADD和DEL操作,并且DEL操作具有等幂性。
  • container必须由ContainerID唯一标识。
  • CRI不能调用同一个网络名称或containerID执行两次ADD(没有相应的DEL)。换句话说,给定的container ID必须只能添加到特定的网络一次。

4. ADD操作

参数

  • Container ID
  • Network namespace 路径,比如 /proc/[pid]/ns/net
  • JSON格式CNI网络配置参数,告诉container需要加入什么样的网络
  • 不同CNI plugin特定的参数
  • container内部的网卡名字

返回值

  • container内部网卡或宿主机上受影响的网卡(如macvlan plugin)列表
  • 给每个网卡分配的网络配置(IP、网关、路由)
  • DNS信息

5. DEL操作

与ADD操作类似

6. 环境变量参数

  • CNI_COMMAND: CNI操作,ADD, DEL or VERSION.
  • CNI_CONTAINERID: Container ID
  • CNI_NETNS: 指向container network namespace文件的路径
  • CNI_IFNAME: container内部网络接口的名字
  • CNI_ARGS: key-value对的额外参数
  • CNI_PATH: CNI plugin binary的路径

 以上的配置必须在CNI plugin可执行文件被调用时作为CNI plugin的STDIN(JSON文件)或者环境变量被传输给CNI plugin。

转载自https://blog.youkuaiyun.com/cloudvtech

四、手动配置和调用macvlan CNI plugin

1. 启动一个container

docker run --net=none -dt centos
ffecae44150e #container ID

docker inspect -f '{{ .State.Pid }}'  ffecae44150e
7077 #container进程号

2. 准备JSON格式CNI需要加入的网络的描述文件

/etc/cni/net.d/10-maclannet.conf 
{
    "name": "macvlannet", #CNI实例名字
    "type": "macvlan",    #CNI类型
    "master": "eth0",     #CNI作用的网卡
    "ipam": {             #IP管理的子plugin的设置

        "type": "host-local", #IP管理plugin的类型
        "subnet": "192.168.122.0/24", #IP管理plugin所需的子网参数
        "routes": [ #IP管理plugin所需的路由参数
            { "dst": "0.0.0.0/0" }
        ]
    } 
}

3. CNI的环境变量参数

export CNI_COMMAND=ADD #CNI的命令,ADD或者DEL
export CNI_IFNAME=eth0 #container内网卡的名字
export CNI_CONTAINERID=ffecae44150e #container的ID
export CNI_PATH=/opt/cni/bin/ #CNI可执行文件的路径
export CNI_NETNS=/proc/7077/ns/net #CNI所需的container namespace的路径

4. 手动运行CNI plugin可执行文件

/opt/cni/bin/macvlan < /etc/cni/net.d/10-maclannet.conf  

输出结果如下:

{
    "ip4": {
        "ip": "192.168.122.3/24",
        "gateway": "192.168.122.1",
        "routes": [
            {
                "dst": "0.0.0.0/0",
                "gw": "192.168.122.1"
            }
        ]
    },
    "dns": {}
} 

包括分配的IP地址、网关、路由等信息


5. 在container内验证CNI的返回结果

docker exec -it ff bash
[root@ffecae44150e /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.122.3  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::858:c0ff:fea8:7a03  prefixlen 64  scopeid 0x20<link>
        ether 0a:58:c0:a8:7a:03  txqueuelen 0  (Ethernet)
        RX packets 5589  bytes 15085040 (14.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5155  bytes 356496 (348.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0 

从宿主机ping container IP

[root@os-cni-test ~]# ping 192.168.122.3
PING 192.168.122.3 (192.168.122.3) 56(84) bytes of data.
64 bytes from 192.168.122.3: icmp_seq=1 ttl=64 time=0.312 ms
64 bytes from 192.168.122.3: icmp_seq=2 ttl=64 time=0.518 ms
64 bytes from 192.168.122.3: icmp_seq=3 ttl=64 time=0.449 ms
^C
--- 192.168.122.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.312/0.426/0.518/0.087 ms 




转载自https://blog.youkuaiyun.com/cloudvtech

<think> 嗯,用户想了解multus cni与hostnetwork的相关信息。之前的对话中系统强调了引用规范,这次用户给出的引用[1]提到multus是Kubernetes多网络接口管理的基石,支持NFV、边缘计算等场景;引用[2]则涉及multus镜像构建的环境变量配置。但用户实际关心的应该是两者的功能关联。 用户作为K8s网络方向的技术人员,可能正在设计需要多网卡且直通宿主网络的方案,比如边缘计算网关。ta特意强调"不是需求参考",说明需要深度原理而非基础教程。核心诉求应该是:如何让Pod既能通过multus附加多网卡,又能保留hostNetwork的特定用途。 先拆解关键点:hostNetwork是启用主机网络栈的Pod配置,会让Pod共享宿主机Network Namespace;而multus本质是CNI元插件,管理多个CNI插件的执行流程。两者关系要从网络栈层面理解——当Pod启用hostNetwork时,kubelet不会调用任何CNI插件(包括multus),这意味着: - 矛盾点:hostNetwork会绕过CNI机制 - 解决方案:需通过其他方式实现需求(如hostPort暴露端口+multus管理副网卡) 用户可能遇到的实际场景是:既需要Pod像主机进程一样监听低端口(需hostNetwork),又需要多张业务网卡(需multus)。这需要明确:hostNetworkmultus是互斥的,但可通过多容器Pod折衷——sidecar容器用hostNetwork主业务容器用multus。 接下来需要验证这个方案。查阅K8s文档确认:一个Pod内所有容器必须共享同一网络命名空间,因此多容器方案行不通。正确做法应是放弃hostNetwork,改用hostPort+multus附加网卡。需要提醒用户注意hostPort的端口冲突风险。 最后补充配置示时,要强调multus的NetworkAttachmentDefinition资源如何定义host-device插件(需预装),并警告nodeSelector的节点亲性配置必要性。用户大概率在生产环境部署,需给出健康检查建议(如用multus-tool验证网卡)。 </think> 以下是关于 Multus CNI 与 HostNetwork 的关联信息及技术解析: --- ### **1. 核心概念** #### **HostNetwork** - **原理**:Pod 直接共享宿主机的网络命名空间(Network Namespace),使用主机 IP 端口资源。 - **特点**: - 性能高(无虚拟网络开销) - 端口与宿主机强绑定,易冲突 - 不支持 Service Mesh、CNI 插件等网络扩展 - **配置示**: ```yaml spec: hostNetwork: true # 启用主机网络 containers: [...] ``` #### **Multus CNI** - **定位**:Kubernetes 的 **"CNI 元插件"**,管理多网络接口。 - **核心能力**: - 为 Pod 附加 **多张网卡**(主网卡 + 辅助网卡) - 支持混合使用不同 CNI 插件(如 Flannel + SR-IOV) - 通过 **NetworkAttachmentDefinition** CRD 定义辅助网络 --- ### **2. 两者关联场景** #### **场景一:HostNetwork 与 Multus 并存** Pod 可 **同时启用 HostNetwork Multus 附加网卡**: ```yaml spec: hostNetwork: true # 使用主机网络栈 annotations: k8s.v1.cni.cncf.io/networks: macvlan-conf # Multus 附加辅助网卡 ``` - **效果**: - `eth0`:继承宿主机网络(HostNetwork) - `net1`:Multus 附加的辅助网卡(如 Macvlan) - **典型用途**: - 需要主机网络性能 + 隔离业务流量的边缘网关 - 主机网络管理 + 多租户数据平面分离 #### **场景二:替代 HostNetwork** 用 Multus 实现 **"类 HostNetwork" 效果**: ```yaml # 创建直通宿主机物理接口的网卡 apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: name: host-device spec: config: '{ "cniVersion": "0.3.1", "type": "host-device", "device": "eth0" # 直接绑定宿主机网卡 }' ``` - **优势**: - 保留 CNI 标准接口,兼容 Service Mesh 等生态 - 规避 HostNetwork 的端口冲突问题 --- ### **3. 配置注意事项** 1. **网络优先级**: - 主网卡(`eth0`)由 `kubenet` 或默认 CNI 管理 - Multus **仅管理辅助网卡**(`net1`、`net2`...) 2. **安全限制**: - HostNetwork Pod 需高权限(`CAP_NET_ADMIN`) - 建议通过 **Pod Security Policy** 限制使用 3. **服务发现**: - HostNetwork Pod 的 Service 需显式设置 `.spec.externalTrafficPolicy: Local`[^1] - Multus 附加网卡的 IP **默认不可被 Service 访问**(需额外 CNI 如 Underlay) --- ### **4. 典型问题排查** | 现象 | 原因 | 解决方案 | |--------------------------|-------------------------------|------------------------------| | Multus 网卡未生效 | CRD 未定义或注解拼写错误 | 检查 `kubectl get nad` | | HostNetwork Pod 端口冲突 | 宿主机端口被占用 | 改用 `hostPort` + 端口调度 | | 辅助网卡无默认路由 | CNI 配置未设网关 | 在 NetworkAttachmentDefinition 中添加路由 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值