# Ubuntu下使用Python脚本创建实验拓扑的方法和示例
实验拓扑是网络工程、分布式系统和云计算等领域中常见的需求,用于模拟复杂的网络环境。在Ubuntu系统中,我们可以通过Python脚本结合多种工具来创建和管理实验拓扑。
## 一、环境准备与虚拟环境配置
### 1.1 创建Python虚拟环境
在开始创建实验拓扑之前,建议先配置独立的Python虚拟环境,以避免依赖冲突。
```bash
# 使用venv创建虚拟环境
python3 -m venv topology_env
source topology_env/bin/activate
# 或者使用conda创建虚拟环境(如果已安装Anaconda)
conda create -n topology_env python=3.8
conda activate topology_env
```
虚拟环境可以确保项目的依赖隔离,避免不同项目间的包版本冲突 [ref_1] [ref_4]。
### 1.2 安装必要的依赖包
根据不同的拓扑创建需求,安装相应的Python包:
```python
# requirements.txt 文件内容
mininet==2.3.0
networkx==2.6.3
matplotlib==3.5.0
docker==5.0.3
paramiko==2.9.0
# 安装命令
pip install -r requirements.txt
```
## 二、使用Mininet创建网络拓扑
### 2.1 基础Mininet拓扑示例
Mininet是创建软件定义网络(SDN)实验环境的理想工具。
```python
#!/usr/bin/env python3
"""
基础网络拓扑创建脚本
使用Mininet创建简单的树形拓扑
"""
from mininet.net import Mininet
from mininet.node import Controller, RemoteController
from mininet.cli import CLI
from mininet.log import setLogLevel, info
from mininet.link import TCLink
def create_topology():
"""创建简单的树形拓扑"""
setLogLevel('info')
# 创建网络实例
net = Mininet(controller=Controller, link=TCLink)
info('*** 添加控制器\n')
# 使用默认的控制器
net.addController('c0')
info('*** 添加主机\n')
h1 = net.addHost('h1', ip='10.0.0.1/24')
h2 = net.addHost('h2', ip='10.0.0.2/24')
h3 = net.addHost('h3', ip='10.0.0.3/24')
h4 = net.addHost('h4', ip='10.0.0.4/24')
info('*** 添加交换机\n')
s1 = net.addSwitch('s1')
s2 = net.addSwitch('s2')
s3 = net.addSwitch('s3')
info('*** 创建链路\n')
# 设置链路带宽和延迟
net.addLink(h1, s1, bw=10, delay='5ms')
net.addLink(h2, s1, bw=10, delay='5ms')
net.addLink(s1, s2, bw=20, delay='10ms')
net.addLink(s2, s3, bw=20, delay='10ms')
net.addLink(s3, h3, bw=10, delay='5ms')
net.addLink(s3, h4, bw=10, delay='5ms')
info('*** 启动网络\n')
net.start()
info('*** 运行CLI\n')
CLI(net)
info('*** 停止网络\n')
net.stop()
if __name__ == '__main__':
create_topology()
```
### 2.2 自定义拓扑类
创建更复杂的自定义拓扑结构:
```python
from mininet.topo import Topo
class CustomTopology(Topo):
"""自定义数据中心拓扑"""
def __init__(self):
Topo.__init__(self)
# 添加核心交换机
core_switch = self.addSwitch('cs1')
# 添加聚合层交换机
agg_switches = []
for i in range(2):
agg_switch = self.addSwitch(f'as{i+1}')
agg_switches.append(agg_switch)
self.addLink(core_switch, agg_switch)
# 添加接入层交换机和主机
for i, agg_switch in enumerate(agg_switches):
for j in range(3):
access_switch = self.addSwitch(f'es{i*3+j+1}')
self.addLink(agg_switch, access_switch)
# 每个接入交换机连接2台主机
for k in range(2):
host = self.addHost(f'h{i*6+j*2+k+1}',
ip=f'10.{i+1}.{j+1}.{k+1}/16')
self.addLink(access_switch, host)
# 使用自定义拓扑
def run_custom_topology():
from mininet.net import Mininet
from mininet.cli import CLI
net = Mininet(topo=CustomTopology())
net.start()
CLI(net)
net.stop()
if __name__ == '__main__':
run_custom_topology()
```
## 三、使用NetworkX创建拓扑可视化
### 3.1 拓扑生成与可视化
NetworkX可以用于生成和分析复杂的网络拓扑。
```python
import networkx as nx
import matplotlib.pyplot as plt
import random
def generate_and_visualize_topology():
"""生成随机拓扑并进行可视化"""
# 创建图实例
G = nx.Graph()
# 添加节点(代表网络设备)
devices = ['Router1', 'Router2', 'Switch1', 'Switch2', 'Switch3',
'Host1', 'Host2', 'Host3', 'Host4']
for device in devices:
G.add_node(device)
# 添加边(代表网络连接)
connections = [
('Router1', 'Switch1'),
('Router1', 'Switch2'),
('Router2', 'Switch3'),
('Switch1', 'Host1'),
('Switch1', 'Host2'),
('Switch2', 'Host3'),
('Switch3', 'Host4')
]
for connection in connections:
G.add_edge(connection[0], connection[1],
weight=random.randint(1, 10))
# 绘制拓扑图
plt.figure(figsize=(12, 8))
# 设置节点位置
pos = nx.spring_layout(G)
# 绘制节点
nx.draw_networkx_nodes(G, pos, node_size=500,
node_color='lightblue', alpha=0.9)
# 绘制边
nx.draw_networkx_edges(G, pos, width=2, alpha=0.6,
edge_color='gray')
# 绘制标签
nx.draw_networkx_labels(G, pos, font_size=10,
font_family='sans-serif')
# 绘制边权重
edge_labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
plt.title('网络拓扑结构图')
plt.axis('off')
plt.tight_layout()
plt.savefig('network_topology.png', dpi=300, bbox_inches='tight')
plt.show()
# 输出拓扑信息
print("网络拓扑信息:")
print(f"节点数量: {G.number_of_nodes()}")
print(f"边数量: {G.number_of_edges()}")
print(f"平均度: {sum(dict(G.degree()).values()) / G.number_of_nodes():.2f}")
if __name__ == '__main__':
generate_and_visualize_topology()
```
## 四、使用Docker创建容器化拓扑
### 4.1 多容器网络拓扑
使用Docker创建包含多个容器的实验环境。
```python
import docker
import time
class DockerTopology:
"""Docker容器拓扑管理类"""
def __init__(self):
self.client = docker.from_env()
self.networks = {}
self.containers = {}
def create_network(self, name, subnet):
"""创建Docker网络"""
try:
network = self.client.networks.create(
name=name,
driver="bridge",
ipam=docker.types.IPAMConfig(
pool_configs=[
docker.types.IPAMPool(subnet=subnet)
]
)
)
self.networks[name] = network
print(f"创建网络: {name} ({subnet})")
return network
except Exception as e:
print(f"创建网络失败: {e}")
return None
def create_container(self, name, image="ubuntu:20.04", network=None):
"""创建Docker容器"""
try:
container = self.client.containers.run(
image=image,
name=name,
detach=True,
tty=True,
stdin_open=True,
network=network.name if network else None
)
self.containers[name] = container
print(f"创建容器: {name}")
return container
except Exception as e:
print(f"创建容器失败: {e}")
return None
def setup_basic_topology(self):
"""设置基础的三层网络拓扑"""
# 创建网络
net1 = self.create_network("net1", "172.20.0.0/24")
net2 = self.create_network("net2", "172.21.0.0/24")
# 创建路由器容器(需要特权模式)
router = self.create_container("router", "ubuntu:20.04")
# 创建终端主机
hosts = []
for i in range(4):
host = self.create_container(f"host{i+1}", "ubuntu:20.04")
hosts.append(host)
# 连接网络(这里需要实际执行Docker网络连接命令)
print("拓扑创建完成,需要手动配置网络连接和路由")
def cleanup(self):
"""清理拓扑环境"""
for container in self.containers.values():
container.stop()
container.remove()
for network in self.networks.values():
network.remove()
print("拓扑环境清理完成")
# 使用示例
if __name__ == '__main__':
topology = DockerTopology()
try:
topology.setup_basic_topology()
# 保持运行一段时间用于测试
time.sleep(300)
finally:
topology.cleanup()
```
## 五、拓扑自动化管理与调度
### 5.1 使用Systemd服务管理拓扑脚本
对于需要长期运行的拓扑实验,可以配置为系统服务 [ref_5]。
```bash
# /etc/systemd/system/topology.service
[Unit]
Description=Network Topology Service
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/topology
ExecStart=/home/ubuntu/topology/env/bin/python /home/ubuntu/topology/main.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
### 5.2 定时任务管理拓扑
使用crontab定时执行拓扑监控任务 [ref_2]。
```bash
# 编辑crontab
crontab -e
# 添加定时任务,每小时检查一次拓扑状态
0 * * * * /home/ubuntu/topology/monitor_topology.sh
# 每天凌晨重启拓扑
0 2 * * * /bin/systemctl restart topology.service
```
## 六、实际应用场景示例
### 6.1 校园网络拓扑模拟
结合校园网环境创建实验拓扑 [ref_3]。
```python
def campus_network_topology():
"""校园网络拓扑模拟"""
from mininet.net import Mininet
from mininet.topo import Topo
class CampusTopo(Topo):
def build(self):
# 核心层
core = self.addSwitch('core-sw')
# 汇聚层 - 各楼宇
buildings = ['lib-sw', 'sci-sw', 'eng-sw', 'adm-sw']
for building in buildings:
bsw = self.addSwitch(building)
self.addLink(core, bsw)
# 接入层 - 每栋楼有多个房间
for i in range(1, 4):
room_sw = self.addSwitch(f'{building}-room{i}')
self.addLink(bsw, room_sw)
# 每个房间多个主机
for j in range(1, 6):
host = self.addHost(f'{building}-room{i}-pc{j}',
ip=f'192.168.{len(hosts)//256}.{(len(hosts)%256)+1}/24')
self.addLink(room_sw, host)
net = Mininet(topo=CampusTopo())
net.start()
# 测试网络连通性
net.pingAll()
net.stop()
```
通过上述方法和示例,可以在Ubuntu系统中灵活创建各种复杂的实验拓扑,满足不同场景下的网络实验需求。每种方法都有其适用场景,可以根据具体需求选择合适的技术方案。