用ovs-docker让容器网络支持Vlan隔离

2024-06-12 13:38

本文主要是介绍用ovs-docker让容器网络支持Vlan隔离,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考文献:
https://blog.csdn.net/canxinghen/article/details/50321573

docker原生使用linux bridge来创建网桥,这样无法使用vlan容器间的网络进行网络隔离。
openvswitch社区提供了一个工具ovs-docker来给docker快速搭建ovs网络。

1、使用ovs创建网桥

ovs-vsctl add-br br0

2、创建3个容器,容器网络模型设置为none

2.1、拉取测试镜像busybox

docker pull busybox:latest

2.2、创建容器

docker run -it -d --name routerA --net=none --privileged busybox
docker run -it -d --name routerB --net=none --privileged busybox
docker run -it -d --name routerC --net=none --privileged busybox

3、使用ovs-docker给容器添加网口

ovs-docker add-port br0 eth0 routerA --ipaddress=192.168.100.1/24
ovs-docker add-port br0 eth0 routerB --ipaddress=192.168.100.2/24
ovs-docker add-port br0 eth1 routerB --ipaddress=192.168.200.2/24
ovs-docker add-port br0 eth0 routerC --ipaddress=192.168.100.3/24

上面给容器routeB,添加了两个网卡;


可见,通过ovs-docker 给容器添加网卡时,会在逻辑交换机上添加端口,在宿主机上添加接口信息

4、测试容器之间是否连通

5、设置vlan隔离

设置Vlan的参数为:网桥名、容器内网口名、容器名、vlan号

ovs-docker set-vlan br0 eth0 routerA 100
ovs-docker set-vlan br0 eth0 routerB 100
ovs-docker set-vlan br0 eth1 routerB 200
ovs-docker set-vlan br0 eth0 routerC 203


6、测试是否连通呢?

7、ovs-docker原理介绍

ovs-docker简单又好用,它的原理就是用netns和veth来作容器和ovs网桥间的桥接!

#!/bin/bash#检查对应的可执行程序有没有在$PATH目录下
#检查的可执行程序有 ovs-vsctl、docker、uuidgen
search_path () {save_IFS=$IFSIFS=:for dir in $PATH; doIFS=$save_IFSif test -x "$dir/$1"; thenreturn 0fidoneIFS=$save_IFSecho >&2 "$0: $1 not found in \$PATH, please install and try again"exit 1
}#给所有的ovs-vsctl命令增加超时时间
ovs_vsctl () {ovs-vsctl --timeout=60 "$@"
}#每个容器是一个netns
#但是只有在 /va/run/netns 下面建立链接,才能将veth挂在到该netns里面
#也只有了链接,才能用ip netns list查询到
create_netns_link () {mkdir -p /var/run/netnsif [ ! -e /var/run/netns/"$PID" ]; thenln -s /proc/"$PID"/ns/net /var/run/netns/"$PID"trap 'delete_netns_link' 0for signal in 1 2 3 13 14 15; do#在收到特定信号后,删掉链接#这些信号有:程序退出、ctrl+c、进程被杀掉等trap 'delete_netns_link; trap - $signal; kill -$signal $$' $signaldonefi
}#删除链接
delete_netns_link () {rm -f /var/run/netns/"$PID"
}#从ovs的数据库中查询port
#查询条件是在创建port的时候设进去的 external_ids 
get_port_for_container_interface () {CONTAINER="$1"INTERFACE="$2"PORT=`ovs_vsctl --data=bare --no-heading --columns=name find interface \external_ids:container_id="$CONTAINER"  \external_ids:container_iface="$INTERFACE"`if [ -z "$PORT" ]; thenecho >&2 "$UTIL: Failed to find any attached port" \"for CONTAINER=$CONTAINER and INTERFACE=$INTERFACE"fiecho "$PORT"
}#给容器添加port,原理是创建一个veth,一端挂在ovs网桥上,一端设到netns里面
add_port () {BRIDGE="$1"INTERFACE="$2"CONTAINER="$3"#参数验证if [ -z "$BRIDGE" ] || [ -z "$INTERFACE" ] || [ -z "$CONTAINER" ]; thenecho >&2 "$UTIL add-port: not enough arguments (use --help for help)"exit 1fi#获取附加参数:ip地址、mac地址、网关信息、mtu信息shift 3while [ $# -ne 0 ]; docase $1 in--ipaddress=*)ADDRESS=`expr X"$1" : 'X[^=]*=\(.*\)'`shift;;--macaddress=*)MACADDRESS=`expr X"$1" : 'X[^=]*=\(.*\)'`shift;;--gateway=*)GATEWAY=`expr X"$1" : 'X[^=]*=\(.*\)'`shift;;--mtu=*)MTU=`expr X"$1" : 'X[^=]*=\(.*\)'`shift;;*)echo >&2 "$UTIL add-port: unknown option \"$1\""exit 1;;esacdone#查看对应容器的特定端口是否已经存在# Check if a port is already attached for the given container and interfacePORT=`get_port_for_container_interface "$CONTAINER" "$INTERFACE" \2>/dev/null`if [ -n "$PORT" ]; thenecho >&2 "$UTIL: Port already attached" \"for CONTAINER=$CONTAINER and INTERFACE=$INTERFACE"exit 1fi#网桥不存在就创建网桥if ovs_vsctl br-exists "$BRIDGE" || \ovs_vsctl add-br "$BRIDGE"; then :; elseecho >&2 "$UTIL: Failed to create bridge $BRIDGE"exit 1fi#通过docker inspect命令获取容器的PID(netns的id)if PID=`docker inspect -f '{{.State.Pid}}' "$CONTAINER"`; then :; elseecho >&2 "$UTIL: Failed to get the PID of the container"exit 1fi#为后面将veth打入netns,需要建立链接create_netns_link#创建一个veth对,veth的名字用uuid,加了“_l”后缀的是挂在网桥上的,加了“_c”的是挂在容器内ID=`uuidgen | sed 's/-//g'`PORTNAME="${ID:0:13}"ip link add "${PORTNAME}_l" type veth peer name "${PORTNAME}_c"# 将“_l”挂到网桥上,挂时增加external_ids信息用于后面查找和删除if ovs_vsctl --may-exist add-port "$BRIDGE" "${PORTNAME}_l" \-- set interface "${PORTNAME}_l" \external_ids:container_id="$CONTAINER" \external_ids:container_iface="$INTERFACE"; then :; elseecho >&2 "$UTIL: Failed to add "${PORTNAME}_l" port to bridge $BRIDGE"ip link delete "${PORTNAME}_l"exit 1fi#拉起“_l”的veth端口ip link set "${PORTNAME}_l" up#将“_c”移到容器的netns里面ip link set "${PORTNAME}_c" netns "$PID"#将“_c”改名为用户设置的接口名,例如ethxip netns exec "$PID" ip link set dev "${PORTNAME}_c" name "$INTERFACE"ip netns exec "$PID" ip link set "$INTERFACE" up#设置mtuif [ -n "$MTU" ]; thenip netns exec "$PID" ip link set dev "$INTERFACE" mtu "$MTU"fi#设置ipif [ -n "$ADDRESS" ]; thenip netns exec "$PID" ip addr add "$ADDRESS" dev "$INTERFACE"fi#设置macif [ -n "$MACADDRESS" ]; thenip netns exec "$PID" ip link set dev "$INTERFACE" address "$MACADDRESS"fi#设置网关if [ -n "$GATEWAY" ]; thenip netns exec "$PID" ip route add default via "$GATEWAY"fi
}#根据添加port时的external_ids查询port后删除
del_port () {BRIDGE="$1"INTERFACE="$2"CONTAINER="$3"if [ "$#" -lt 3 ]; thenusageexit 1fiPORT=`get_port_for_container_interface "$CONTAINER" "$INTERFACE"`if [ -z "$PORT" ]; thenexit 1fiovs_vsctl --if-exists del-port "$PORT"ip link delete "$PORT"
}del_ports () {BRIDGE="$1"CONTAINER="$2"if [ "$#" -lt 2 ]; thenusageexit 1fiPORTS=`ovs_vsctl --data=bare --no-heading --columns=name find interface \external_ids:container_id="$CONTAINER"`if [ -z "$PORTS" ]; thenexit 0fifor PORT in $PORTS; doovs_vsctl --if-exists del-port "$PORT"ip link delete "$PORT"done
}#使用ovs的set port tag的方式设置vlan
set_vlan () {BRIDGE="$1"INTERFACE="$2"CONTAINER_ID="$3"VLAN="$4"if [ "$#" -lt 4 ]; thenusageexit 1fiPORT=`get_port_for_container_interface "$CONTAINER_ID" "$INTERFACE"`if [ -z "$PORT" ]; thenexit 1fiovs_vsctl set port "$PORT" tag="$VLAN"
}usage() {cat << EOF
${UTIL}: Performs integration of Open vSwitch with Docker.
usage: ${UTIL} COMMANDCommands:add-port BRIDGE INTERFACE CONTAINER [--ipaddress="ADDRESS"][--gateway=GATEWAY] [--macaddress="MACADDRESS"][--mtu=MTU]Adds INTERFACE inside CONTAINER and connects it as a portin Open vSwitch BRIDGE. Optionally, sets ADDRESS onINTERFACE. ADDRESS can include a '/' to represent networkprefix length. Optionally, sets a GATEWAY, MACADDRESSand MTU.  e.g.:${UTIL} add-port br-int eth1 c474a0e2830e--ipaddress=192.168.1.2/24 --gateway=192.168.1.1--macaddress="a2:c3:0d:49:7f:f8" --mtu=1450del-port BRIDGE INTERFACE CONTAINERDeletes INTERFACE inside CONTAINER and removes itsconnection to Open vSwitch BRIDGE. e.g.:${UTIL} del-port br-int eth1 c474a0e2830edel-ports BRIDGE CONTAINERRemoves all Open vSwitch interfaces from CONTAINER. e.g.:${UTIL} del-ports br-int c474a0e2830eset-vlan BRIDGE INTERFACE CONTAINER VLANConfigures the INTERFACE of CONTAINER attached to BRIDGEto become an access port of VLAN. e.g.:${UTIL} set-vlan br-int eth1 c474a0e2830e 5
Options:-h, --help        display this help message.
EOF
}#查看$PATH是否存在对应的命令
UTIL=$(basename $0)
search_path ovs-vsctl
search_path docker
search_path uuidgenif (ip netns) > /dev/null 2>&1; then :; elseecho >&2 "$UTIL: ip utility not found (or it does not support netns),"\"cannot proceed"exit 1
fiif [ $# -eq 0 ]; thenusageexit 0
fi#根据输入的参数决定动作
case $1 in"add-port")shiftadd_port "$@"exit 0;;"del-port")shiftdel_port "$@"exit 0;;"del-ports")shiftdel_ports "$@"exit 0;;"set-vlan")shiftset_vlan "$@"exit 0;;-h | --help)usageexit 0;;*)echo >&2 "$UTIL: unknown command \"$1\" (use --help for help)"exit 1;;
esac

把上面的脚本,放到这个目录下,就行
文件名是ovs-docker

这篇关于用ovs-docker让容器网络支持Vlan隔离的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1054376

相关文章

华为鸿蒙HarmonyOS 5.1官宣7月开启升级! 首批支持名单公布

《华为鸿蒙HarmonyOS5.1官宣7月开启升级!首批支持名单公布》在刚刚结束的华为Pura80系列及全场景新品发布会上,除了众多新品的发布,还有一个消息也点燃了所有鸿蒙用户的期待,那就是Ha... 在今日的华为 Pura 80 系列及全场景新品发布会上,华为宣布鸿蒙 HarmonyOS 5.1 将于 7

Linux网络配置之网桥和虚拟网络的配置指南

《Linux网络配置之网桥和虚拟网络的配置指南》这篇文章主要为大家详细介绍了Linux中配置网桥和虚拟网络的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、网桥的配置在linux系统中配置一个新的网桥主要涉及以下几个步骤:1.为yum仓库做准备,安装组件epel-re

MySQL中的事务隔离级别详解

《MySQL中的事务隔离级别详解》在MySQL中,事务(Transaction)是一个执行单元,它要么完全执行,要么完全回滚,以保证数据的完整性和一致性,下面给大家介绍MySQL中的事务隔离级别详解,... 目录一、事务并发问题二、mysql 事务隔离级别1. READ UNCOMMITTED(读未提交)2

python如何下载网络文件到本地指定文件夹

《python如何下载网络文件到本地指定文件夹》这篇文章主要为大家详细介绍了python如何实现下载网络文件到本地指定文件夹,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...  在python中下载文件到本地指定文件夹可以通过以下步骤实现,使用requests库处理HTTP请求,并结合o

ubuntu如何部署Dify以及安装Docker? Dify安装部署指南

《ubuntu如何部署Dify以及安装Docker?Dify安装部署指南》Dify是一个开源的大模型应用开发平台,允许用户快速构建和部署基于大语言模型的应用,ubuntu如何部署Dify呢?详细请... Dify是个不错的开源LLM应用开发平台,提供从 Agent 构建到 AI workflow 编排、RA

Docker安装MySQL镜像的详细步骤(适合新手小白)

《Docker安装MySQL镜像的详细步骤(适合新手小白)》本文详细介绍了如何在Ubuntu环境下使用Docker安装MySQL5.7版本,包括从官网拉取镜像、配置MySQL容器、设置权限及内网部署,... 目录前言安装1.访问docker镜像仓库官网2.找到对应的版本,复制右侧的命令即可3.查看镜像4.启

MySQL中隔离级别的使用详解

《MySQL中隔离级别的使用详解》:本文主要介绍MySQL中隔离级别的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录引言undo log的作用MVCC的实现有以下几个重要因素如何根据这些因素判断数据值?可重复读和已提交读区别?串行化隔离级别的实现幻读和可

Linux高并发场景下的网络参数调优实战指南

《Linux高并发场景下的网络参数调优实战指南》在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃,本文基于真实案例分析,从参数解读、问题诊断到优... 目录一、问题背景:当并发连接遇上性能瓶颈1.1 案例环境1.2 初始参数分析二、深度诊断:连接状态与

debian12安装docker的实现步骤

《debian12安装docker的实现步骤》本文主要介绍了debian12安装docker的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录步骤 1:更新你的系统步骤 2:安装依赖项步骤 3:添加 docker 的官方 GPG 密钥步骤

SpringIOC容器Bean初始化和销毁回调方式

《SpringIOC容器Bean初始化和销毁回调方式》:本文主要介绍SpringIOC容器Bean初始化和销毁回调方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录前言1.@Bean指定初始化和销毁方法2.实现接口3.使用jsR250总结前言Spring Bea