掘金 后端 ( ) • 2024-04-12 13:52

CNI(Container Networking Interface) 容器网络接口

cnitool

cnitool是一个执行CNI配置的简单程序。它将在已创建的网络命名空间中添加或删除接口。

环境变量:

  • NETCONFPATH:默认从/etc/cni/net.d下所有以 *.conf*.json结尾的文件中获取环境变量
  • CNI_PATH:CNI插件路径

简单的示例

安装

go get github.com/containernetworking/cni
go install github.com/containernetworking/cni/cnitool

git clone https://github.com/containernetworking/plugins.git
cd plugins
./build_linux.sh

创建cni网络

echo '{"cniVersion":"0.4.0","name":"myptp","type":"ptp","ipMasq":true,"ipam":{"type":"host-local","subnet":"172.16.29.0/24","routes":[{"dst":"0.0.0.0/0"}]}}' | tee /etc/cni/net.d/10-myptp.conf

绑定cni

# 创建ns
sudo ip netns add testing
# 把容器添加到cni网络中
sudo CNI_PATH=./bin cnitool add myptp /var/run/netns/testing
# 检查
sudo CNI_PATH=./bin cnitool check myptp /var/run/netns/testing
# 测试
sudo ip -n testing addr
sudo ip netns exec testing ping -c 1 4.2.2.2
# 清理
sudo CNI_PATH=./bin cnitool del myptp /var/run/netns/testing
sudo ip netns del testing

IPAM插件

ip地址分配插件

  • dhcp: 在宿主机上运行一个守护进程,代表容器发出dhcp请求
  • host-local: 维护已分配ip的本地数据库
  • static: 为容器分配静态IPv4/IPv6地址

Main插件

接口的创建插件

  • bridge:创建一个桥接,将主机和容器添加到其中
  • ipvlan:在容器中添加ipvlan接口
  • macvlan:创建一个新的MAC地址,将所有流量转发到容器
  • ptp:创建一对veth虚拟接口
  • host-device:将已经存在的设备移动到容器中
  • vlan:创建vlan接口

Windows的接口

  • win-bridge:创建一个桥接,将主机和容器添加到其中
  • win-overlay:为容器创建overlay接口

ptp

https://www.cni.dev/plugins/current/main/ptp/

ptp插件通过使用veth虚拟设备在容器和主机之间创建点对点链接。host-local IPAM插件可以用来给容器分配ip。容器接口的流量将通过主机接口路由。

集群多cni部署:手工配置ptp-cni

有些时候因为网络环境的特殊性,并不能实现每个节点都在相同的网络环境下,我们可以通过独立部署cni的方式实现集群内的互通。

ptp节点信息

prifcy-k8s-xx1.hz.163.org 7.34.xx.xx1 pod:10.178.128.0/24
prifcy-k8s-xx2.hz.163.org 7.34.xx.xx2 pod:10.178.129.0/24

k8s集群中禁止原有cni调度

      tolerations: # 配置了污点容忍
      - operator: Exists
    spec:
      affinity:
        nodeAffinity: # 添加节点亲和性
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: node.netease.com/ptp
                operator: DoesNotExist # 使用不存在

检查cni插件

$ ls /opt/cni/bin
bandwidth  bridge  dhcp  firewall  flannel  host-device  host-local  ipvlan  loopback  macvlan  portmap  ptp  sbr  scud-cni-bgp  static  tuning  vlan
$ less /etc/default/kubelet-extra
--kubeconfig=/etc/kubernetes/kubelet.conf \
--cni-bin-dir=/opt/cni/bin \
--cni-conf-dir=/etc/cni/net.d \
--config=/var/lib/kubelet/config.yaml \
--network-plugin=cni \

配置kubelet-nci,编写/etc/cni/net.d/ptp.conflist,两个节点区分一下subnet

{
  "cniVersion":"0.3.1",
  "name":"ptp-network",
  "plugins":[
    {
      "name": "ptpnet",
      "type": "ptp",
      "ipam": {
        "type": "host-local",
        "subnet": "10.178.128.0/24",
        "routes": [
          {
            "dst": "0.0.0.0/0"
          }
        ]
      },
      "mtu": 1450,
      "ipMasq": false
    }
  ]
}

重启kubelet: systemctl restart kubelet.service,查看pod已经可以正常分配ip了

skiff-agent-c2pln  1/1     Running   3   62s     10.178.128.6    prifcy-k8s-ptp-xx1.hz.163.org
skiff-agent-pbrsk  1/1     Running   3   62s     10.178.129.6    prifcy-k8s-ptp-xx2.hz.163.org

现在需要保证集群内pod网络互通

# ptp节点上启动tunl0
ip link set tunl0 up
# 2台ptp节点上也要添加对应的路由,保证ptp节点之间互通
ip route add 10.178.129.0/24 via 7.34.73.xx1 dev tunl0 onlink

ip route add 10.178.128.0/24 via 7.34.73.xx2 dev tunl0 onlink

# 贵州集群正常cni节点添加路由,节点上本身就启动了tunl0
ip route add 10.178.128.0/24 via 7.34.73.xx1 dev tunl0 onlink
ip route add 10.178.129.0/24 via 7.34.73.xx2 dev tunl0 onlink
# 完成后就可以在正常节点上ping通ptp的网段了
ping -c1 10.178.129.3

ptp的pod可以访问外网

iptables -t nat -A POSTROUTING -s 10.178.128.0/24 -d 10.48.160.0/22 -j RETURN # pod网段
iptables -t nat -A POSTROUTING -s 10.178.128.0/24 -d 10.48.164.0/26 -j RETURN # node网段
iptables -t nat -A POSTROUTING -s 10.178.128.0/24 -j MASQUERADE