docker中使用linux 的namespce 技术实现容器隔离,本文模拟测试实现构建一个虚拟网络
配置网络
整个网络图如下
模拟4个网络隔离后的命名空间,连接到一个虚拟网桥
setp1 创建network namespace
创建4个 network namespace 用于隔离网络
setp2 创建网桥
创建网桥用于连通4个namespace
在Linux的语境中,Bridge和Switch(交换机)是一个概念。Bridge是一个虚拟网络设备,所以具有网络设备的特征,可以配置IP、MAC地址等
需要使用brctl 命令
centos安装
yum install bridge-utils
ubuntu安装
apt install bridge-utils
使用brctl show 查看当前存在的网桥
使用brctl addbr 【自定义名称】 创建网桥
setp3 创建虚拟设备 veth pair
**创建虚拟网卡 **
例如
ip link add tap1 type veth peer name veth1
以上命令的意思就是创建 名称为tap1的虚拟网卡,网卡连线的另一边名称是veth1,
也可以使用ip link add tap1 type veth 这样会自动创建一个网卡连线名称为veth0与tap1相连
创建4对网卡与网卡的连线用于连接网桥和命名空间
ip link add tap1 type veth peer name veth1
ip link add tap2 type veth peer name veth2
ip link add tap3 type veth peer name veth3
ip link add tap4 type veth peer name veth4
setp4 虚拟网卡对添加到名字空间和虚拟网桥上
把虚拟网卡添加到 名字空间
ip link set tap1 netns ns1
ip link set tap2 netns ns2
ip link set tap3 netns ns3
ip link set tap4 netns ns4
把虚拟网卡的另一边 添加到网桥交换机上
brctl addif testbridge veth1
brctl addif testbridge veth2
brctl addif testbridge veth3
brctl addif testbridge veth4
setp5 在网络命名空间配置好网卡的ip
**注意需要使用 ip netns exec 在指定的网络命名空间中执行命令 **
ip netns exec ns1 ip addr add local 192.168.10.202/24 dev tap1
ip netns exec ns2 ip addr add local 192.168.10.203/24 dev tap2
ip netns exec ns3 ip addr add local 192.168.10.204/24 dev tap3
ip netns exec ns4 ip addr add local 192.168.10.205/24 dev tap4
setp6 启动所有相关设备
需要启动的设备
- 虚拟网桥 testbridge
- 虚拟网卡 tap1~tap4
- 虚拟网卡另一端 veth1 ~ veth4
ip link set testbridge up
ip link set veth1 up
ip link set veth2 up
ip link set veth3 up
ip link set veth4 up
ip netns exec ns1 ip link set tap1 up
ip netns exec ns2 ip link set tap2 up
ip netns exec ns3 ip link set tap3 up
ip netns exec ns4 ip link set tap4 up
setp7 测试联通
注意: 只能在网络命名空间内部执行ping 操作
整个网络环境配置完成
java程序测试
java 程序测试 其实类似ping 操作 只是更加直观
测试打印网络设备信息
代码
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
/**
* 展示名字空间内的网络设备信息
* @author jimliu
*
*/
public class Show {
public static void main(String[] args) {
try {
Enumeration ifaces = NetworkInterface.getNetworkInterfaces();
while(ifaces.hasMoreElements()) {
NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
System.out.println("设备名称:" + iface.getDisplayName());
Enumeration inetAddrs = iface.getInetAddresses();
while (inetAddrs.hasMoreElements()) {
InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
System.out.println("设备地址:" + inetAddr.getHostAddress());
}
System.out.println("### \n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
实现了网络设备的隔离
测试java 客户端服务器请求
服务器代码
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(6677);
System.out.println("start server");
while(true){
Socket s = ss.accept();
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
byte[] b = new byte[48];
bis.read(b);
System.out.println("收到客户端消息: " + new String(b));
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
String msg = "收到客户: " + new String(b);
bos.write(msg.getBytes());
bos.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端代码
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
try {
String ip = InetAddress.getLocalHost().getHostAddress();
Socket s = new Socket("192.168.10.205", 6677);
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
String msg = "hello~ from " + ip;
bos.write(msg.getBytes());
bos.flush();
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
byte[] b = new byte[48];
bis.read(b);
System.out.println("get server back: " + new String(b));
bis.close();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
在命名空间4启动 server 在宿主机上运行client 连接超时
在命名空间4启动 server 在命名空间1 ~3 上运行client