欢迎光临
我们一直在努力

容器网络CNI实战:从零搭建网络插件

容器网络CNI实战:从零搭建网络插件

一、CNI概述

CNI(Container Network Interface)是容器网络的标准化接口,定义了容器网络配置和管理的规范。

1.1 CNI架构

┌─────────────────────┐
│ Container │
└──────────┬──────────┘


┌─────────────────────┐
│ CNI Plugin │
│ (bridge, macvlan, │
│ flannel, calico) │
└──────────┬──────────┘


┌─────────────────────┐
│ Network │
│ (veth, bridge, │
│ route, iptables) │
└─────────────────────┘

1.2 CNI规范

CNI插件需要支持以下操作:

  • ADD:将容器添加到网络
  • DEL:从网络中移除容器
  • CHECK:检查网络状态
  • VERSION:返回版本信息

二、CNI配置文件

2.1 配置文件结构

{
"cniVersion": "0.4.0",
"name": "my-network",
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/16",
"routes": [
{ "dst": "0.0.0.0/0" }
]
}
}

2.2 配置参数说明

参数说明必填
cniVersion CNI版本
name 网络名称
type 插件类型
bridge 网桥名称
isGateway 是否作为网关
ipMasq 是否启用IP伪装
ipam IP地址管理配置

三、Bridge插件实战

3.1 安装CNI工具

# 下载CNI插件
mkdir -p /opt/cni/bin
cd /opt/cni/bin
wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz
tar -xzf cni-plugins-linux-amd64-v1.3.0.tgz

3.2 创建配置文件

mkdir -p /etc/cni/net.d
cat > /etc/cni/net.d/10-bridge.conf <<EOF
{
"cniVersion": "0.4.0",
"name": "bridge-network",
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local",
"subnet": "10.100.0.0/16",
"gateway": "10.100.0.1",
"routes": [
{ "dst": "0.0.0.0/0" }
]
}
}
EOF

3.3 手动调用CNI插件

# 创建网络命名空间
ip netns add test-namespace

# 创建veth对
ip link add veth0 type veth peer name veth0-br

# 将veth一端加入网桥
ip link set veth0-br master cni0

# 将veth另一端加入命名空间
ip link set veth0 netns test-namespace

# 调用CNI ADD命令
cat > /tmp/cni-args.json <<EOF
{
"containerid": "test-container",
"netns": "/var/run/netns/test-namespace",
"ifname": "eth0",
"args": {
"ignoreUnknown": true
}
}
EOF

./bridge < /tmp/cni-args.json

3.4 Go语言调用CNI

package main

import (
"fmt"
"os"

"github.com/containernetworking/cni/pkg/invoke"
"github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/types/current"
)

func main() {
netConf := []byte(`{
"cniVersion": "0.4.0",
"name": "test-network",
"type": "bridge",
"ipam": {
"type": "host-local",
"subnet": "10.200.0.0/16"
}
}`)

result, err := invoke.ExecPlugin(
"/opt/cni/bin/bridge",
netConf,
[]string{
"CNI_COMMAND=ADD",
"CNI_CONTAINERID=test-container",
"CNI_NETNS=/var/run/netns/test",
"CNI_IFNAME=eth0",
"CNI_PATH=/opt/cni/bin",
},
)

if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\\n", err)
os.Exit(1)
}

fmt.Println(string(result))
}

四、Flannel网络方案

4.1 Flannel架构

┌─────────────────┐ VXLAN ┌─────────────────┐
│ Node A │ ──────────────> │ Node B │
│ ┌───────────┐ │ │ ┌───────────┐ │
│ │ Container │ │ │ │ Container │ │
│ └─────┬─────┘ │ │ └─────┬─────┘ │
│ │ │ │ │ │
│ ┌─────┴─────┐ │ │ ┌─────┴─────┐ │
│ │ flannel0 │ │ │ │ flannel0 │ │
│ └─────┬─────┘ │ │ └─────┬─────┘ │
│ │ │ │ │ │
│ ┌─────┴─────┐ │ │ ┌─────┴─────┐ │
│ │ eth0 │ │────────────────│ │ eth0 │ │
│ └───────────┘ │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘

4.2 安装Flannel

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

4.3 Flannel配置

apiVersion: v1
kind: ConfigMap
metadata:
name: kube-flannel-cfg
namespace: kube-system
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}

五、Calico网络方案

5.1 Calico架构

┌─────────────────────────────────────────────────────────────┐
│ Felix Agent │
│ (管理路由、iptables规则) │
└─────────────────────────────────────────────────────────────┘

┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ BGP Router │ │ IPAM │ │ Policy Engine │
│ (路由分发) │ │ (IP分配) │ │ (网络策略) │
└─────────────────┘ └─────────────────┘ └─────────────────┘

5.2 安装Calico

kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

5.3 Calico网络策略

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: default
spec:
podSelector: {}
policyTypes:
– Ingress
– Egress

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-http
namespace: default
spec:
podSelector:
matchLabels:
app: web
ingress:
– from:
– ipBlock:
cidr: 10.0.0.0/8
ports:
– protocol: TCP
port: 80

六、自定义CNI插件开发

6.1 插件结构

package main

import (
"fmt"
"os"

"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/cni/pkg/version"
)

func cmdAdd(args *skel.CmdArgs) error {
// 解析配置
conf, err := parseConfig(args.StdinData)
if err != nil {
return fmt.Errorf("failed to parse config: %v", err)
}

// 创建网络接口
iface, err := setupInterface(args)
if err != nil {
return fmt.Errorf("failed to setup interface: %v", err)
}

// 配置IP地址
result, err := assignIP(conf, iface)
if err != nil {
return fmt.Errorf("failed to assign IP: %v", err)
}

return types.PrintResult(result, conf.CNIVersion)
}

func cmdDel(args *skel.CmdArgs) error {
// 清理网络接口
return teardownInterface(args)
}

func main() {
skel.PluginMain(cmdAdd, cmdDel, version.All)
}

6.2 网络配置解析

type NetConf struct {
types.NetConf
Bridge string `json:"bridge"`
VlanID int `json:"vlanID"`
MTU int `json:"mtu"`
}

func parseConfig(data []byte) (*NetConf, error) {
conf := &NetConf{}
if err := json.Unmarshal(data, conf); err != nil {
return nil, fmt.Errorf("failed to unmarshal config: %v", err)
}

// 设置默认值
if conf.Bridge == "" {
conf.Bridge = "cni0"
}
if conf.MTU == 0 {
conf.MTU = 1500
}

return conf, nil
}

6.3 接口创建

func setupInterface(args *skel.CmdArgs) (*current.Interface, error) {
// 创建veth对
hostVeth, contVeth, err := netlink.VethAdd(args.Netns, args.IfName)
if err != nil {
return nil, fmt.Errorf("failed to create veth: %v", err)
}

// 将host端加入网桥
bridge, err := netlink.LinkByName(conf.Bridge)
if err != nil {
return nil, fmt.Errorf("failed to find bridge: %v", err)
}

if err := netlink.LinkSetMaster(hostVeth, bridge); err != nil {
return nil, fmt.Errorf("failed to add to bridge: %v", err)
}

return &current.Interface{
Name: contVeth.Name,
Mac: contVeth.HardwareAddr.String(),
Sandbox: args.Netns,
}, nil
}

七、网络诊断与调试

7.1 常用命令

# 查看网络命名空间
ip netns list

# 进入命名空间执行命令
ip netns exec test-namespace ip addr

# 查看路由表
ip route show

# 查看iptables规则
iptables -t nat -L

# 查看网桥信息
brctl show

# 查看CNI配置
cat /etc/cni/net.d/*.conf

7.2 网络连通性测试

# 测试Pod间通信
kubectl exec -it pod1 — ping pod2-ip

# 测试Pod到外部网络
kubectl exec -it pod1 — ping 8.8.8.8

# 检查DNS解析
kubectl exec -it pod1 — nslookup kubernetes.default

八、性能优化

8.1 调整MTU

{
"cniVersion": "0.4.0",
"name": "optimized-network",
"type": "bridge",
"mtu": 9001,
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/16"
}
}

8.2 使用高性能驱动

apiVersion: v1
kind: ConfigMap
metadata:
name: kube-flannel-cfg
data:
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "host-gw"
}
}

8.3 禁用不必要的功能

{
"cniVersion": "0.4.0",
"name": "minimal-network",
"type": "bridge",
"ipMasq": false,
"ipam": {
"type": "host-local",
"subnet": "10.200.0.0/16"
}
}

九、最佳实践总结

9.1 插件选择建议

场景推荐插件原因
单节点 bridge 简单高效
多节点 flannel 易于部署
大规模集群 calico 高性能、灵活策略
网络隔离要求高 calico 强大的网络策略

9.2 配置建议

  • 子网规划:根据集群规模合理分配CIDR
  • MTU设置:跨节点通信建议使用Jumbo Frame
  • IPAM选择:host-local适合小规模,dhcp适合大规模
  • 安全策略:生产环境建议启用网络策略

9.3 监控指标

  • 网络延迟:Pod间通信延迟
  • 带宽利用率:各节点网络使用情况
  • 丢包率:网络传输质量
  • 连接数:容器网络连接状态

通过合理选择和配置CNI插件,可以构建高效、可靠的容器网络环境。

赞(0)
未经允许不得转载:171主机测评 » 容器网络CNI实战:从零搭建网络插件
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址