用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运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

poj 3181 网络流,建图。

题意: 农夫约翰为他的牛准备了F种食物和D种饮料。 每头牛都有各自喜欢的食物和饮料,而每种食物和饮料都只能分配给一头牛。 问最多能有多少头牛可以同时得到喜欢的食物和饮料。 解析: 由于要同时得到喜欢的食物和饮料,所以网络流建图的时候要把牛拆点了。 如下建图: s -> 食物 -> 牛1 -> 牛2 -> 饮料 -> t 所以分配一下点: s  =  0, 牛1= 1~

poj 3068 有流量限制的最小费用网络流

题意: m条有向边连接了n个仓库,每条边都有一定费用。 将两种危险品从0运到n-1,除了起点和终点外,危险品不能放在一起,也不能走相同的路径。 求最小的费用是多少。 解析: 抽象出一个源点s一个汇点t,源点与0相连,费用为0,容量为2。 汇点与n - 1相连,费用为0,容量为2。 每条边之间也相连,费用为每条边的费用,容量为1。 建图完毕之后,求一条流量为2的最小费用流就行了

poj 2112 网络流+二分

题意: k台挤奶机,c头牛,每台挤奶机可以挤m头牛。 现在给出每只牛到挤奶机的距离矩阵,求最小化牛的最大路程。 解析: 最大值最小化,最小值最大化,用二分来做。 先求出两点之间的最短距离。 然后二分匹配牛到挤奶机的最大路程,匹配中的判断是在这个最大路程下,是否牛的数量达到c只。 如何求牛的数量呢,用网络流来做。 从源点到牛引一条容量为1的边,然后挤奶机到汇点引一条容量为m的边

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么? K8s的架构原理  控制平面(Control plane)         kube-apiserver         etcd         kube-scheduler         kube-controller-manager         cloud-controlle

配置InfiniBand (IB) 和 RDMA over Converged Ethernet (RoCE) 网络

配置InfiniBand (IB) 和 RDMA over Converged Ethernet (RoCE) 网络 服务器端配置 在服务器端,你需要确保安装了必要的驱动程序和软件包,并且正确配置了网络接口。 安装 OFED 首先,安装 Open Fabrics Enterprise Distribution (OFED),它包含了 InfiniBand 所需的驱动程序和库。 sudo