用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

相关文章

如何使用Docker部署FTP和Nginx并通过HTTP访问FTP里的文件

《如何使用Docker部署FTP和Nginx并通过HTTP访问FTP里的文件》本文介绍了如何使用Docker部署FTP服务器和Nginx,并通过HTTP访问FTP中的文件,通过将FTP数据目录挂载到N... 目录docker部署FTP和Nginx并通过HTTP访问FTP里的文件1. 部署 FTP 服务器 (

解读docker运行时-itd参数是什么意思

《解读docker运行时-itd参数是什么意思》在Docker中,-itd参数组合用于在后台运行一个交互式容器,同时保持标准输入和分配伪终端,这种方式适合需要在后台运行容器并保持交互能力的场景... 目录docker运行时-itd参数是什么意思1. -i(或 --interactive)2. -t(或 --

Docker部署Jenkins持续集成(CI)工具的实现

《Docker部署Jenkins持续集成(CI)工具的实现》Jenkins是一个流行的开源自动化工具,广泛应用于持续集成(CI)和持续交付(CD)的环境中,本文介绍了使用Docker部署Jenkins... 目录前言一、准备工作二、设置变量和目录结构三、配置 docker 权限和网络四、启动 Jenkins

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

定价129元!支持双频 Wi-Fi 5的华为AX1路由器发布

《定价129元!支持双频Wi-Fi5的华为AX1路由器发布》华为上周推出了其最新的入门级Wi-Fi5路由器——华为路由AX1,建议零售价129元,这款路由器配置如何?详细请看下文介... 华为 Wi-Fi 5 路由 AX1 已正式开售,新品支持双频 1200 兆、配有四个千兆网口、提供可视化智能诊断功能,建

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

docker如何删除悬空镜像

《docker如何删除悬空镜像》文章介绍了如何使用Docker命令删除悬空镜像,以提高服务器空间利用率,通过使用dockerimage命令结合filter和awk工具,可以过滤出没有Tag的镜像,并将... 目录docChina编程ker删除悬空镜像前言悬空镜像docker官方提供的方式自定义方式总结docker

Spring核心思想之浅谈IoC容器与依赖倒置(DI)

《Spring核心思想之浅谈IoC容器与依赖倒置(DI)》文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyB... 目录一、控制反转 IoC二、依赖倒置 DI1. 详细概念2. Spring 中 DI 的实现原理三、

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如