用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

相关文章

如何高效移除C++关联容器中的元素

《如何高效移除C++关联容器中的元素》关联容器和顺序容器有着很大不同,关联容器中的元素是按照关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的,本文介绍了如何高效移除C+... 目录一、简介二、移除给定位置的元素三、移除与特定键值等价的元素四、移除满足特android定条件的元

Docker镜像修改hosts及dockerfile修改hosts文件的实现方式

《Docker镜像修改hosts及dockerfile修改hosts文件的实现方式》:本文主要介绍Docker镜像修改hosts及dockerfile修改hosts文件的实现方式,具有很好的参考价... 目录docker镜像修改hosts及dockerfile修改hosts文件准备 dockerfile 文

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

SpringKafka消息发布之KafkaTemplate与事务支持功能

《SpringKafka消息发布之KafkaTemplate与事务支持功能》通过本文介绍的基本用法、序列化选项、事务支持、错误处理和性能优化技术,开发者可以构建高效可靠的Kafka消息发布系统,事务支... 目录引言一、KafkaTemplate基础二、消息序列化三、事务支持机制四、错误处理与重试五、性能优

Docker镜像pull失败两种解决办法小结

《Docker镜像pull失败两种解决办法小结》有时候我们在拉取Docker镜像的过程中会遇到一些问题,:本文主要介绍Docker镜像pull失败两种解决办法的相关资料,文中通过代码介绍的非常详细... 目录docker 镜像 pull 失败解决办法1DrQwWCocker 镜像 pull 失败解决方法2总

如何将Tomcat容器替换为Jetty容器

《如何将Tomcat容器替换为Jetty容器》:本文主要介绍如何将Tomcat容器替换为Jetty容器问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Tomcat容器替换为Jetty容器修改Maven依赖配置文件调整(可选)重新构建和运行总结Tomcat容器替

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

通过Docker Compose部署MySQL的详细教程

《通过DockerCompose部署MySQL的详细教程》DockerCompose作为Docker官方的容器编排工具,为MySQL数据库部署带来了显著优势,下面小编就来为大家详细介绍一... 目录一、docker Compose 部署 mysql 的优势二、环境准备与基础配置2.1 项目目录结构2.2 基

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用