跳至正文

MacVLAN

Linux 内核原生支持 Macvlan

Macvlan 是 Linux 内核提供的一种网络虚拟化技术,它允许在同一个物理网卡上创建多个虚拟网络接口,每个虚拟接口可以有自己的 MAC 地址。这样做的好处是:

  • 每个虚拟接口可以像独立网卡一样直接在二层网络通信。
  • 可以用来隔离流量、创建容器网络(Docker、LXC 等常用)。
  • 性能接近原生网卡,因为大部分流量直接在内核层转发,不经过额外的用户态处理。
  • Macvlan 支持从 Linux 内核 2.6.24 开始引入。
  • 现代 Linux 发行版(如 CentOS 7/8、Ubuntu 20.04/22.04、Debian 12 等)内核都原生集成了 macvlan 驱动。
  • 模块名为 macvlan,通常是内置的或可以通过 modprobe macvlan 加载。
lsmod | grep macvlan
# 或者
modprobe macvlan 
#加载macvlan模块

Macvlan 的四个模式

private 模式

描述:同一物理网卡上的 Macvlan 接口彼此隔离,不能直接互相通信,但可以和外部网络通信。

特点

  • 接口之间完全隔离。
  • 适合容器之间需要独立 IP,但不互通的场景。
macvlan0   macvlan1   macvlan2
   |          |          |
   └─────────> 外部网络

vepa 模式 (Virtual Ethernet Port Aggregator)

描述:同一物理网卡上的接口通信必须通过外部交换机转发。

特点

  • 内部接口不能直接互通。
  • 适合企业交换机环境,通过交换机统一转发流量
macvlan0   macvlan1
   |          |
   └───> 交换机 <───┘

bridge 模式

描述:同一物理网卡上的 Macvlan 接口可以互相通信,也能访问外部网络。

特点

  • 内部接口互通。
  • 最常用模式,容器互通和外部访问都方便。
macvlan0 <--> macvlan1 <--> macvlan2
       \                /
        ---> 外部网络 <---

passthru 模式

描述:每个 Macvlan 接口独占物理网卡,只有一个接口可以使用物理网卡。

特点

  • 高性能,类似 SR-IOV。
  • 一个物理网卡只能绑定一个 passthru 接口。
[eth0] ---> macvlan0 (独占)

小结

模式内部接口互通外部网络访问典型应用
private容器隔离
vepa企业交换机
bridge容器互通
passthru高性能直通

创建MacVLAN

注意:
nmcli 创建的 macvlan 接口会被 NetworkManager 接管(永久生效)
和用 ip link 临时创建的接口是两套机制(临时生效)

临时配置(使用 ip 命令)

假设物理网卡是 eth0,我们先创建一个 macvlan 接口,再给它分配 IP:

# 创建 macvlan 接口
ip link add link eth0 name macvlan0 type macvlan mode bridge

# 启动接口
ip link set macvlan0 up

# 分配 IP 地址
ip addr add 192.168.1.198/24 dev macvlan0

# 设置默认网关(如需要)
ip route add default via 192.168.1.1 dev macvlan0

这样 macvlan0 就有了 IP,可以 ping 网关或外网了。
⚠️ 注意:如果你给物理网卡 eth0macvlan0 配置了同一网段的 IP,它们之间可能无法直接互通(这是 macvlan 的特性)。

永久配置(开机自动生效)

nmcli 创建 macvlan 接口

比如在物理网卡 eth0 上创建一个 macvlan 接口 macvlan0

nmcli connection add type macvlan \
    ifname macvlan0 \
    dev eth0 \
    mode bridge \
    ip4 192.168.1.100/24 \
    gw4 192.168.1.1

nmcli connection up macvlan0
#启用接口

参数说明:

  • ifname macvlan0 → 新接口名
  • dev eth0 → 绑定的物理网卡
  • mode bridge → macvlan 模式(可选:privatevepabridgepassthru
  • ip4 → IPv4 地址和掩码
  • gw4 → 网关

这样 macvlan0 就带 IP 上线了。

因为 nmcli 配置会写入 NetworkManager 的配置目录(通常 /etc/NetworkManager/system-connections/),所以重启后接口依然存在,不需要额外操作。

RHEL通过配置文件创建

创建文件 /etc/sysconfig/network-scripts/ifcfg-macvlan0

DEVICE=macvlan0
DEVICETYPE=Macvlan
PHYSDEV=eth0
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.1.100
PREFIX=24
GATEWAY=192.168.1.1
MACVLAN_MODE=bridge

然后重启网络:systemctl restart network

小结

  • ip link add → 临时接口(重启后消失)。
  • nmcli → 永久接口(由 NetworkManager 管理)。

脚本:创建MacVLAN的交互式操作

#!/bin/bash
# CentOS7 Macvlan 管理脚本

# 自动加载 macvlan 模块
echo ">>> 检查 macvlan 模块..."
if ! lsmod | grep -q macvlan; then
    echo "未加载 macvlan 模块,正在加载..."
    modprobe macvlan
    if [ $? -eq 0 ]; then
        echo "macvlan 模块已成功加载"
    else
        echo "加载 macvlan 模块失败,请检查内核是否支持"
        exit 1
    fi
else
    echo "macvlan 模块已加载"
fi

# 注意事项
cat <<EOF

================ 注意事项 ================
1. Macvlan 接口与宿主机默认不能互通
2. 请确保目标物理网卡已连接网络
3. DNS 默认为 223.5.5.5
4. 子网掩码默认 255.255.255.0
==========================================

EOF

# 选择物理网卡
function select_parent_if() {
    echo ">>> 检测可用物理网卡..."
    IFACES=($(ls /sys/class/net | grep -Ev '^(lo|docker.*|veth.*|macvlan.*|virbr.*)$'))
    if [ ${#IFACES[@]} -eq 0 ]; then
        echo "未找到可用物理网卡"
        exit 1
    fi

    echo "可用物理网卡列表:"
    for i in "${!IFACES[@]}"; do
        echo "$((i+1))) ${IFACES[$i]}"
    done

    while true; do
        read -p "请选择物理网卡编号 [1-${#IFACES[@]}]: " choice
        if [[ "$choice" =~ ^[0-9]+$ ]] && [ $choice -ge 1 ] && [ $choice -le ${#IFACES[@]} ]; then
            PARENT_IF=${IFACES[$((choice-1))]}
            echo "已选择物理网卡: $PARENT_IF"
            break
        else
            echo "无效输入,请重新选择"
        fi
    done
}

# 获取用户输入函数
function get_network_config() {
    select_parent_if
    read -p "请输入新建 macvlan 接口名称 (例如 macvlan0): " VLAN_IF
    echo "请选择 macvlan 模式 (回车默认 bridge):"
    echo "1) bridge"
    echo "2) private"
    echo "3) vepa"
    echo "4) passthru"
    read -p "请输入选项 [1-4]: " MODE_CHOICE
    case $MODE_CHOICE in
        2) VLAN_MODE="private" ;;
        3) VLAN_MODE="vepa" ;;
        4) VLAN_MODE="passthru" ;;
        *) VLAN_MODE="bridge" ;;
    esac
    read -p "请输入 IP 地址 (例如 192.168.1.100): " IP_ADDR
    read -p "请输入子网掩码 (默认 24 请使用CIDR格式): " NETMASK
    NETMASK=${NETMASK:-255.255.255.0}
    read -p "请输入网关 (可留空): " GATEWAY
    read -p "请输入 DNS (默认 223.5.5.5): " DNS
    DNS=${DNS:-223.5.5.5}
}

# 使用 ip 命令创建 macvlan
function create_with_ip() {
    get_network_config
    echo ">>> 正在创建 macvlan 接口 $VLAN_IF (模式: $VLAN_MODE)..."
    ip link add $VLAN_IF link $PARENT_IF type macvlan mode $VLAN_MODE
    ip addr add $IP_ADDR/$NETMASK dev $VLAN_IF
    ip link set $VLAN_IF up
    [ -n "$GATEWAY" ] && ip route add default via $GATEWAY dev $VLAN_IF
    echo "nameserver $DNS" > /etc/resolv.conf
    echo ">>> 创建完成!"
    show_summary
}

# 使用 nmcli 命令创建 macvlan
function create_with_nmcli() {
    get_network_config
    echo ">>> 正在使用 nmcli 创建 macvlan 接口 $VLAN_IF (模式: $VLAN_MODE)..."
    nmcli connection add type macvlan ifname $VLAN_IF dev $PARENT_IF mode $VLAN_MODE ip4 $IP_ADDR/$NETMASK gw4 $GATEWAY
    nmcli connection modify $VLAN_IF ipv4.dns "$DNS"
    nmcli connection up $VLAN_IF
    echo ">>> 创建完成!"
    show_summary
}

# 删除所有 macvlan 接口
function delete_all_macvlan() {
    echo ">>> 正在删除所有 macvlan 接口..."
    for IF in $(ip -o link show | awk -F': ' '{print $2}' | grep macvlan); do
        ip link delete $IF
        echo "已删除接口: $IF"
    done
    echo ">>> 所有 macvlan 接口已删除"
}

# 总结信息
function show_summary() {
    echo
    echo "================ 配置信息总结 ================"
    echo "物理网卡:   $PARENT_IF"
    echo "macvlan接口: $VLAN_IF"
    echo "模式:       $VLAN_MODE"
    echo "IP 地址:    $IP_ADDR"
    echo "子网掩码:   $NETMASK"
    echo "网关:       ${GATEWAY:-无}"
    echo "DNS:        $DNS"
    echo "============================================"
}

# 菜单
while true; do
    echo
    echo "========= Macvlan 管理菜单 ========="
    echo "1) 使用 ip 创建 macvlan"
    echo "2) 使用 nmcli 创建 macvlan"
    echo "3) 删除所有 macvlan 接口"
    echo "4) 退出"
    echo "==================================="
    read -p "请选择操作 [1-4]: " choice

    case $choice in
        1) create_with_ip ;;
        2) create_with_nmcli ;;
        3) delete_all_macvlan ;;
        4) echo "退出程序"; exit 0 ;;
        *) echo "无效选项,请重新输入" ;;
    esac
done

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注