学习目标
通过本章学习,您将能够:
- 理解 Docker Swarm 网络架构和原理
- 掌握 Overlay 网络的创建和配置
- 学会服务发现和负载均衡机制
- 了解网络安全和隔离策略
- 掌握网络故障排除和性能优化
1. Swarm 网络架构
1.1 网络类型概述
内置网络类型
# 查看默认网络
docker network ls
# 默认网络类型:
# bridge - 单机桥接网络
# host - 主机网络
# none - 无网络
# overlay - 跨主机覆盖网络
# ingress - 入口负载均衡网络
网络驱动程序
# Bridge 驱动(单机)
- 默认的单机网络驱动
- 适用于单节点容器通信
- 提供网络隔离
# Overlay 驱动(多机)
- 跨主机容器通信
- 基于 VXLAN 封装
- 支持服务发现
- 内置负载均衡
# Host 驱动
- 直接使用主机网络
- 无网络隔离
- 最佳性能
# None 驱动
- 禁用网络
- 完全隔离
- 需要手动配置
1.2 Overlay 网络原理
VXLAN 封装
# VXLAN(Virtual Extensible LAN)特性:
- 24位 VNI(VXLAN Network Identifier)
- 支持 1600万个虚拟网络
- UDP 封装(默认端口 4789)
- 二层网络在三层网络上的扩展
# 数据包封装格式:
# [外层IP头][UDP头][VXLAN头][内层以太网帧]
网络组件
# 网络组件说明:
# 1. libnetwork
- Docker 网络库
- 提供网络抽象层
- 支持多种网络驱动
# 2. docker_gwbridge
- 容器到主机的桥接网络
- 提供外部连接
- 每个节点一个
# 3. ingress 网络
- 内置的负载均衡网络
- 路由网格(Routing Mesh)
- 处理发布的端口
# 4. 自定义 overlay 网络
- 用户创建的跨主机网络
- 服务间通信
- 支持加密
1.3 网络架构图
# Swarm 网络架构示意:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Manager Node │ │ Worker Node │ │ Worker Node │
│ │ │ │ │ │
│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │ Container │ │ │ │ Container │ │ │ │ Container │ │
│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │
│ │ │ │ │ │ │ │ │
│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │ Overlay │ │ │ │ Overlay │ │ │ │ Overlay │ │
│ │ Network │ │ │ │ Network │ │ │ │ Network │ │
│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │
│ │ │ │ │ │ │ │ │
│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │docker_gwbridge│ │ │docker_gwbridge│ │ │docker_gwbridge│
│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │
│ │ │ │ │ │ │ │ │
└────────┼────────┘ └────────┼────────┘ └────────┼────────┘
│ │ │
┌────┴──────────────────────┴──────────────────────┴────┐
│ Physical Network │
└─────────────────────────────────────────────────────┘
2. Overlay 网络管理
2.1 创建 Overlay 网络
基本网络创建
# 创建基本 overlay 网络
docker network create --driver overlay my-network
# 创建可附加的网络(允许独立容器连接)
docker network create --driver overlay --attachable my-attachable-network
# 创建带子网的网络
docker network create \
--driver overlay \
--subnet 10.0.1.0/24 \
--gateway 10.0.1.1 \
my-subnet-network
# 查看网络列表
docker network ls
# 查看网络详情
docker network inspect my-network
高级网络配置
# 创建加密网络
docker network create \
--driver overlay \
--opt encrypted \
secure-network
# 创建多子网网络
docker network create \
--driver overlay \
--subnet 10.0.1.0/24 \
--subnet 10.0.2.0/24 \
--gateway 10.0.1.1 \
--gateway 10.0.2.1 \
multi-subnet-network
# 创建带 VLAN 的网络
docker network create \
--driver overlay \
--opt com.docker.network.driver.overlay.vxlanid_list=4097 \
vlan-network
# 创建自定义 MTU 网络
docker network create \
--driver overlay \
--opt com.docker.network.driver.mtu=1450 \
custom-mtu-network
网络配置脚本
#!/bin/bash
# create-networks.sh
# 网络配置数组
declare -A NETWORKS=(
["frontend"]="10.0.1.0/24"
["backend"]="10.0.2.0/24"
["database"]="10.0.3.0/24"
["monitoring"]="10.0.4.0/24"
)
echo "Creating overlay networks..."
for network in "${!NETWORKS[@]}"; do
subnet=${NETWORKS[$network]}
gateway=$(echo $subnet | sed 's/0\/24/1/')
echo "Creating network: $network with subnet: $subnet"
docker network create \
--driver overlay \
--subnet $subnet \
--gateway $gateway \
--opt encrypted \
--attachable \
$network
if [ $? -eq 0 ]; then
echo "✓ Network $network created successfully"
else
echo "✗ Failed to create network $network"
fi
done
echo "\nNetwork creation completed"
docker network ls --filter driver=overlay
2.2 网络连接管理
服务网络连接
# 创建服务时连接网络
docker service create --name web \
--network frontend \
--network backend \
nginx
# 连接现有服务到网络
docker service update --network-add backend web
# 从网络断开服务
docker service update --network-rm frontend web
# 查看服务网络连接
docker service inspect web --format '{{range .Spec.TaskTemplate.Networks}}{{.Target}} {{end}}'
容器网络连接
# 连接独立容器到 overlay 网络(需要 --attachable)
docker run -d --name test-container --network my-attachable-network alpine sleep 3600
# 连接运行中的容器到网络
docker network connect backend test-container
# 断开容器网络连接
docker network disconnect backend test-container
# 查看容器网络信息
docker inspect test-container --format '{{range $net, $conf := .NetworkSettings.Networks}}{{$net}}: {{$conf.IPAddress}} {{end}}'
网络别名配置
# 创建带网络别名的服务
docker service create --name database \
--network backend \
--network-alias db \
--network-alias mysql \
mysql:8.0
# 更新服务网络别名
docker service update \
--network-rm backend \
--network-add name=backend,alias=primary-db \
database
# 测试网络别名解析
docker run --rm --network backend alpine nslookup db
docker run --rm --network backend alpine ping -c 3 mysql
2.3 网络隔离策略
网络分层设计
# 三层网络架构
# 1. 前端网络(DMZ)
docker network create \
--driver overlay \
--subnet 10.1.0.0/16 \
--opt encrypted \
frontend-dmz
# 2. 应用网络
docker network create \
--driver overlay \
--subnet 10.2.0.0/16 \
--opt encrypted \
application-tier
# 3. 数据网络
docker network create \
--driver overlay \
--subnet 10.3.0.0/16 \
--opt encrypted \
data-tier
# 部署分层服务
# 负载均衡器(前端网络 + 应用网络)
docker service create --name lb \
--network frontend-dmz \
--network application-tier \
--publish 80:80 \
--publish 443:443 \
nginx
# 应用服务(应用网络 + 数据网络)
docker service create --name app \
--network application-tier \
--network data-tier \
--replicas 3 \
my-app:latest
# 数据库(仅数据网络)
docker service create --name database \
--network data-tier \
--constraint 'node.labels.type == database' \
mysql:8.0
网络访问控制
#!/bin/bash
# network-acl.sh
# 创建隔离的网络环境
create_isolated_environment() {
local env_name=$1
local subnet_base=$2
echo "Creating isolated environment: $env_name"
# 创建环境专用网络
docker network create \
--driver overlay \
--subnet ${subnet_base}.0/24 \
--opt encrypted \
--label environment=$env_name \
${env_name}-network
# 创建环境网关服务(用于外部访问控制)
docker service create --name ${env_name}-gateway \
--network ${env_name}-network \
--publish published=0,target=80,protocol=tcp \
--label environment=$env_name \
nginx:alpine
echo "Environment $env_name created with network ${env_name}-network"
}
# 创建多个隔离环境
create_isolated_environment "development" "10.10"
create_isolated_environment "staging" "10.20"
create_isolated_environment "production" "10.30"
# 验证网络隔离
echo "\nVerifying network isolation..."
docker network ls --filter label=environment
# 测试跨网络连通性(应该失败)
echo "\nTesting cross-network connectivity..."
docker run --rm --network development-network alpine ping -c 1 -W 1 10.20.0.1 || echo "✓ Networks are properly isolated"
3. 服务发现机制
3.1 内置服务发现
DNS 服务发现
# Swarm 内置 DNS 服务发现特性:
# - 服务名解析到虚拟 IP(VIP)
# - 任务名解析到具体容器 IP
# - 网络别名支持
# - 自动负载均衡
# 创建测试服务
docker service create --name web --replicas 3 --network backend nginx
docker service create --name api --replicas 2 --network backend my-api:latest
# 测试服务发现
docker run --rm --network backend alpine nslookup web
docker run --rm --network backend alpine nslookup api
# 查看服务 VIP
docker service inspect web --format '{{range .Endpoint.VirtualIPs}}{{.NetworkID}} {{.Addr}}{{end}}'
服务发现配置
# 禁用服务发现(使用 dnsrr 模式)
docker service create --name web \
--replicas 3 \
--endpoint-mode dnsrr \
--network backend \
nginx
# 查看端点模式
docker service inspect web --format '{{.Spec.EndpointSpec.Mode}}'
# VIP 模式 vs DNSRR 模式
# VIP (Virtual IP):
# - 默认模式
# - 服务名解析到单个虚拟 IP
# - 内置负载均衡
# - 适用于大多数场景
# DNSRR (DNS Round Robin):
# - 服务名解析到所有任务 IP
# - 客户端负责负载均衡
# - 适用于需要客户端控制的场景
3.2 外部服务发现
Consul 集成
# 部署 Consul 集群
docker service create --name consul \
--replicas 3 \
--network backend \
--publish 8500:8500 \
--env CONSUL_BIND_INTERFACE=eth0 \
consul:latest agent -server -bootstrap-expect=3 -ui -client=0.0.0.0
# 配置服务注册到 Consul
docker service create --name web \
--network backend \
--label consul.service=web \
--label consul.port=80 \
--label consul.health.http=/health \
nginx
# 使用 Registrator 自动注册服务
docker service create --name registrator \
--mode global \
--mount type=bind,source=/var/run/docker.sock,target=/tmp/docker.sock \
--network backend \
gliderlabs/registrator:latest consul://consul:8500
服务发现脚本
#!/bin/bash
# service-discovery.sh
# 获取服务信息
get_service_info() {
local service_name=$1
echo "=== Service Discovery Info for $service_name ==="
# 基本服务信息
echo "Service Details:"
docker service inspect $service_name --format '
Name: {{.Spec.Name}}
Replicas: {{.Spec.Replicas}}
Endpoint Mode: {{.Spec.EndpointSpec.Mode}}'
# VIP 信息
echo "\nVirtual IPs:"
docker service inspect $service_name --format '{{range .Endpoint.VirtualIPs}}Network: {{.NetworkID}} VIP: {{.Addr}}{{end}}'
# 任务信息
echo "\nRunning Tasks:"
docker service ps $service_name --filter desired-state=running --format "table {{.Name}}\t{{.Node}}\t{{.CurrentState}}"
# DNS 解析测试
echo "\nDNS Resolution Test:"
docker run --rm --network backend alpine nslookup $service_name 2>/dev/null || echo "DNS resolution failed"
# 连通性测试
echo "\nConnectivity Test:"
docker run --rm --network backend alpine ping -c 1 -W 1 $service_name 2>/dev/null && echo "✓ Service is reachable" || echo "✗ Service is not reachable"
}
# 服务发现健康检查
service_discovery_health_check() {
echo "=== Service Discovery Health Check ==="
# 检查 DNS 服务
echo "Checking DNS service..."
docker run --rm --network backend alpine nslookup google.com > /dev/null 2>&1 && echo "✓ DNS is working" || echo "✗ DNS is not working"
# 检查内部服务解析
echo "\nChecking internal service resolution..."
for service in $(docker service ls --format '{{.Name}}'); do
docker run --rm --network backend alpine nslookup $service > /dev/null 2>&1 && echo "✓ $service" || echo "✗ $service"
done
# 检查网络连通性
echo "\nChecking network connectivity..."
docker run --rm --network backend alpine ping -c 1 -W 1 8.8.8.8 > /dev/null 2>&1 && echo "✓ External connectivity" || echo "✗ External connectivity"
}
# 使用示例
if [ "$1" = "health" ]; then
service_discovery_health_check
elif [ -n "$1" ]; then
get_service_info $1
else
echo "Usage: $0 <service-name> | health"
fi
4. 负载均衡
4.1 内置负载均衡
路由网格(Routing Mesh)
# 路由网格特性:
# - 所有节点都可以接收发布端口的流量
# - 自动路由到健康的任务实例
# - 支持多种负载均衡算法
# - 无需外部负载均衡器
# 创建发布端口的服务
docker service create --name web \
--replicas 4 \
--publish 80:80 \
nginx
# 测试负载均衡
for i in {1..10}; do
curl -s http://localhost | grep -o "Server: .*"
done
# 查看端口发布信息
docker service inspect web --format '{{range .Endpoint.Ports}}{{.Protocol}}:{{.PublishedPort}}->{{.TargetPort}}{{end}}'
负载均衡算法
# Swarm 支持的负载均衡算法:
# 1. Round Robin(默认)
# - 轮询分发请求
# - 简单均匀分布
# - 适用于大多数场景
# 2. Least Connections
# - 连接数最少优先
# - 适用于长连接场景
# - 需要外部负载均衡器支持
# 3. IP Hash
# - 基于客户端 IP 哈希
# - 会话保持
# - 需要外部负载均衡器支持
# 配置会话保持(使用外部负载均衡器)
docker service create --name web \
--replicas 3 \
--label traefik.enable=true \
--label traefik.http.services.web.loadbalancer.sticky=true \
nginx
4.2 外部负载均衡
HAProxy 配置
# 创建 HAProxy 配置
cat > haproxy.cfg << 'EOF'
global
daemon
log stdout local0
maxconn 4096
defaults
mode http
log global
option httplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend web_frontend
bind *:80
default_backend web_backend
backend web_backend
balance roundrobin
option httpchk GET /health
server web1 web.1:80 check
server web2 web.2:80 check
server web3 web.3:80 check
frontend stats
bind *:8404
stats enable
stats uri /stats
stats refresh 30s
EOF
# 部署 HAProxy 服务
docker config create haproxy-config haproxy.cfg
docker service create --name haproxy \
--config source=haproxy-config,target=/usr/local/etc/haproxy/haproxy.cfg \
--publish 80:80 \
--publish 8404:8404 \
--network backend \
haproxy:alpine
Nginx 负载均衡
# 创建 Nginx 配置
cat > nginx.conf << 'EOF'
events {
worker_connections 1024;
}
http {
upstream backend {
least_conn;
server web.1:80 max_fails=3 fail_timeout=30s;
server web.2:80 max_fails=3 fail_timeout=30s;
server web.3:80 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
}
EOF
# 部署 Nginx 负载均衡器
docker config create nginx-config nginx.conf
docker service create --name nginx-lb \
--config source=nginx-config,target=/etc/nginx/nginx.conf \
--publish 80:80 \
--network backend \
nginx:alpine
4.3 负载均衡监控
负载均衡健康检查
#!/bin/bash
# lb-health-check.sh
LB_SERVICE="nginx-lb"
BACKEND_SERVICE="web"
HEALTH_ENDPOINT="/health"
LB_URL="http://localhost"
# 检查负载均衡器状态
check_lb_status() {
echo "=== Load Balancer Health Check ==="
# 检查负载均衡器服务状态
lb_replicas=$(docker service ps $LB_SERVICE --filter desired-state=running --filter current-state=running | wc -l)
echo "Load Balancer Replicas: $lb_replicas"
# 检查后端服务状态
backend_replicas=$(docker service ps $BACKEND_SERVICE --filter desired-state=running --filter current-state=running | wc -l)
echo "Backend Service Replicas: $backend_replicas"
# 健康检查
echo "\nHealth Check Results:"
for i in {1..5}; do
response=$(curl -s -o /dev/null -w "%{http_code}" $LB_URL$HEALTH_ENDPOINT)
if [ "$response" = "200" ]; then
echo "✓ Health check $i: OK"
else
echo "✗ Health check $i: Failed (HTTP $response)"
fi
sleep 1
done
}
# 负载分布测试
test_load_distribution() {
echo "\n=== Load Distribution Test ==="
declare -A server_count
# 发送多个请求测试负载分布
for i in {1..20}; do
server=$(curl -s $LB_URL | grep -o "Server: [^<]*" | cut -d' ' -f2)
if [ -n "$server" ]; then
((server_count[$server]++))
fi
done
# 显示分布结果
echo "Request distribution:"
for server in "${!server_count[@]}"; do
echo " $server: ${server_count[$server]} requests"
done
# 计算分布均匀性
total_servers=${#server_count[@]}
if [ $total_servers -gt 0 ]; then
expected_per_server=$((20 / total_servers))
echo "\nExpected requests per server: $expected_per_server"
for server in "${!server_count[@]}"; do
actual=${server_count[$server]}
variance=$((actual - expected_per_server))
echo " $server variance: $variance"
done
fi
}
# 性能测试
performance_test() {
echo "\n=== Performance Test ==="
# 使用 ab (Apache Bench) 进行性能测试
if command -v ab > /dev/null; then
echo "Running Apache Bench test..."
ab -n 1000 -c 10 $LB_URL$HEALTH_ENDPOINT
else
echo "Apache Bench not available, using curl for basic test"
start_time=$(date +%s.%N)
for i in {1..100}; do
curl -s $LB_URL$HEALTH_ENDPOINT > /dev/null
done
end_time=$(date +%s.%N)
duration=$(echo "$end_time - $start_time" | bc)
rps=$(echo "scale=2; 100 / $duration" | bc)
echo "100 requests completed in ${duration}s"
echo "Requests per second: $rps"
fi
}
# 执行所有检查
check_lb_status
test_load_distribution
performance_test
5. 网络安全
5.1 网络加密
启用网络加密
# 创建加密网络
docker network create \
--driver overlay \
--opt encrypted \
secure-network
# 查看网络加密状态
docker network inspect secure-network --format '{{.Options.encrypted}}'
# 加密特性:
# - 使用 AES-GCM 算法
# - 自动密钥轮换
# - 透明加密/解密
# - 性能影响约 10-15%
证书管理
# 查看集群证书信息
docker info --format '{{.Swarm.Cluster.TLSInfo}}'
# 轮换集群证书
docker swarm ca --rotate
# 配置外部 CA
docker swarm ca --external-ca protocol=cfssl,url=https://ca.example.com
# 查看节点证书
docker node inspect self --format '{{.Description.TLSInfo}}'
5.2 网络隔离
微分段策略
#!/bin/bash
# network-microsegmentation.sh
# 创建微分段网络架构
create_microsegmented_network() {
echo "Creating microsegmented network architecture..."
# 前端网络(仅 Web 服务)
docker network create \
--driver overlay \
--subnet 10.1.0.0/24 \
--opt encrypted \
--label tier=frontend \
frontend-only
# 应用网络(Web + API)
docker network create \
--driver overlay \
--subnet 10.2.0.0/24 \
--opt encrypted \
--label tier=application \
app-tier
# 数据网络(API + Database)
docker network create \
--driver overlay \
--subnet 10.3.0.0/24 \
--opt encrypted \
--label tier=data \
data-tier
# 管理网络(监控和管理服务)
docker network create \
--driver overlay \
--subnet 10.4.0.0/24 \
--opt encrypted \
--label tier=management \
mgmt-tier
echo "Microsegmented networks created"
}
# 部署分层服务
deploy_tiered_services() {
echo "Deploying tiered services..."
# Web 层(前端 + 应用网络)
docker service create --name web \
--network frontend-only \
--network app-tier \
--publish 80:80 \
--publish 443:443 \
--replicas 2 \
nginx:alpine
# API 层(应用 + 数据网络)
docker service create --name api \
--network app-tier \
--network data-tier \
--replicas 3 \
my-api:latest
# 数据库层(仅数据网络)
docker service create --name database \
--network data-tier \
--constraint 'node.labels.type == database' \
--replicas 1 \
mysql:8.0
# 监控服务(管理网络 + 其他网络用于监控)
docker service create --name monitoring \
--network mgmt-tier \
--network app-tier \
--network data-tier \
--publish 3000:3000 \
grafana/grafana
echo "Tiered services deployed"
}
# 验证网络隔离
verify_network_isolation() {
echo "Verifying network isolation..."
# 测试 Web 到 Database 的直接访问(应该失败)
echo "Testing Web -> Database (should fail):"
docker run --rm --network frontend-only alpine ping -c 1 -W 1 database 2>/dev/null && echo "✗ Isolation failed" || echo "✓ Properly isolated"
# 测试 Web 到 API 的访问(应该成功)
echo "Testing Web -> API (should succeed):"
docker run --rm --network app-tier alpine ping -c 1 -W 1 api 2>/dev/null && echo "✓ Connection allowed" || echo "✗ Connection blocked"
# 测试 API 到 Database 的访问(应该成功)
echo "Testing API -> Database (should succeed):"
docker run --rm --network data-tier alpine ping -c 1 -W 1 database 2>/dev/null && echo "✓ Connection allowed" || echo "✗ Connection blocked"
}
create_microsegmented_network
deploy_tiered_services
verify_network_isolation
5.3 访问控制
基于标签的访问控制
# 为节点添加安全标签
docker node update --label-add security.zone=dmz node1
docker node update --label-add security.zone=internal node2
docker node update --label-add security.zone=secure node3
# 基于安全区域部署服务
docker service create --name public-web \
--constraint 'node.labels.security.zone == dmz' \
--network frontend-only \
--publish 80:80 \
nginx
docker service create --name internal-api \
--constraint 'node.labels.security.zone == internal' \
--network app-tier \
my-api:latest
docker service create --name secure-db \
--constraint 'node.labels.security.zone == secure' \
--network data-tier \
mysql:8.0
网络策略实现
#!/bin/bash
# network-policy.sh
# 实现基本的网络策略
implement_network_policy() {
local policy_name=$1
local source_network=$2
local target_network=$3
local action=$4 # allow/deny
echo "Implementing network policy: $policy_name"
echo "Source: $source_network -> Target: $target_network (Action: $action)"
# 创建策略标签
docker network update \
--label-add policy.name=$policy_name \
--label-add policy.source=$source_network \
--label-add policy.target=$target_network \
--label-add policy.action=$action \
$target_network
# 注意:Docker Swarm 原生不支持网络策略
# 这里只是演示概念,实际实现需要:
# 1. 使用 Calico、Weave 等 CNI 插件
# 2. 配置 iptables 规则
# 3. 使用服务网格(如 Istio)
}
# 定义网络策略
define_network_policies() {
echo "Defining network policies..."
# 允许前端访问应用层
implement_network_policy "frontend-to-app" "frontend-only" "app-tier" "allow"
# 允许应用层访问数据层
implement_network_policy "app-to-data" "app-tier" "data-tier" "allow"
# 拒绝前端直接访问数据层
implement_network_policy "frontend-to-data-deny" "frontend-only" "data-tier" "deny"
# 允许管理网络访问所有层
implement_network_policy "mgmt-to-all" "mgmt-tier" "*" "allow"
}
# 查看网络策略
view_network_policies() {
echo "\nCurrent network policies:"
for network in $(docker network ls --filter driver=overlay --format '{{.Name}}'); do
policies=$(docker network inspect $network --format '{{range $key, $value := .Labels}}{{if eq $key "policy.name"}}{{$value}}{{end}}{{end}}')
if [ -n "$policies" ]; then
echo "Network: $network"
docker network inspect $network --format '{{range $key, $value := .Labels}}{{if contains $key "policy"}} {{$key}}: {{$value}}{{end}}{{end}}'
fi
done
}
define_network_policies
view_network_policies
6. 网络故障排除
6.1 网络诊断工具
基本诊断命令
# 查看网络列表和状态
docker network ls
docker network inspect <network-name>
# 查看服务网络连接
docker service inspect <service-name> --format '{{range .Spec.TaskTemplate.Networks}}{{.Target}} {{end}}'
# 查看容器网络信息
docker inspect <container-id> --format '{{range $net, $conf := .NetworkSettings.Networks}}{{$net}}: {{$conf.IPAddress}} {{end}}'
# 查看路由表
docker run --rm --privileged --net=host alpine ip route
# 查看网络接口
docker run --rm --privileged --net=host alpine ip addr
# 查看 iptables 规则
docker run --rm --privileged --net=host alpine iptables -L
网络连通性测试
#!/bin/bash
# network-connectivity-test.sh
TEST_NETWORK="backend"
TEST_SERVICES=("web" "api" "database")
# 基本连通性测试
basic_connectivity_test() {
echo "=== Basic Connectivity Test ==="
for service in "${TEST_SERVICES[@]}"; do
echo "Testing connectivity to $service:"
# Ping 测试
docker run --rm --network $TEST_NETWORK alpine ping -c 3 -W 1 $service && echo "✓ Ping successful" || echo "✗ Ping failed"
# DNS 解析测试
docker run --rm --network $TEST_NETWORK alpine nslookup $service && echo "✓ DNS resolution successful" || echo "✗ DNS resolution failed"
echo "---"
done
}
# 端口连通性测试
port_connectivity_test() {
echo "\n=== Port Connectivity Test ==="
# 定义服务端口
declare -A service_ports=(
["web"]="80"
["api"]="8080"
["database"]="3306"
)
for service in "${!service_ports[@]}"; do
port=${service_ports[$service]}
echo "Testing port connectivity to $service:$port:"
# 使用 nc (netcat) 测试端口
docker run --rm --network $TEST_NETWORK alpine nc -zv $service $port && echo "✓ Port $port accessible" || echo "✗ Port $port not accessible"
echo "---"
done
}
# 网络性能测试
network_performance_test() {
echo "\n=== Network Performance Test ==="
# 创建测试服务器
docker run -d --name test-server --network $TEST_NETWORK alpine sh -c 'nc -l -p 8080'
sleep 2
# 测试带宽
echo "Testing network bandwidth:"
docker run --rm --network $TEST_NETWORK alpine sh -c 'dd if=/dev/zero bs=1M count=10 | nc test-server 8080' &
# 测试延迟
echo "Testing network latency:"
docker run --rm --network $TEST_NETWORK alpine ping -c 10 test-server | tail -1
# 清理测试服务器
docker rm -f test-server
}
# 网络配置验证
network_config_verification() {
echo "\n=== Network Configuration Verification ==="
# 检查网络驱动
echo "Network driver:"
docker network inspect $TEST_NETWORK --format '{{.Driver}}'
# 检查子网配置
echo "\nSubnet configuration:"
docker network inspect $TEST_NETWORK --format '{{range .IPAM.Config}}{{.Subnet}} {{.Gateway}}{{end}}'
# 检查加密状态
echo "\nEncryption status:"
docker network inspect $TEST_NETWORK --format '{{.Options.encrypted}}'
# 检查连接的服务
echo "\nConnected services:"
for service in $(docker service ls --format '{{.Name}}'); do
networks=$(docker service inspect $service --format '{{range .Spec.TaskTemplate.Networks}}{{.Target}} {{end}}')
if [[ $networks == *"$TEST_NETWORK"* ]]; then
echo " $service"
fi
done
}
# 执行所有测试
basic_connectivity_test
port_connectivity_test
network_performance_test
network_config_verification
6.2 常见问题解决
网络连接问题
#!/bin/bash
# network-troubleshoot.sh
# 诊断网络连接问题
diagnose_network_issues() {
local service_name=$1
echo "=== Diagnosing Network Issues for $service_name ==="
# 1. 检查服务状态
echo "1. Service Status:"
docker service ps $service_name
# 2. 检查网络配置
echo "\n2. Network Configuration:"
docker service inspect $service_name --format '{{range .Spec.TaskTemplate.Networks}}Network: {{.Target}}{{end}}'
# 3. 检查端点配置
echo "\n3. Endpoint Configuration:"
docker service inspect $service_name --format '{{.Endpoint}}'
# 4. 检查任务网络状态
echo "\n4. Task Network Status:"
for task in $(docker service ps $service_name --filter desired-state=running --format '{{.Name}}'); do
container_id=$(docker ps --filter name=$task --format '{{.ID}}')
if [ -n "$container_id" ]; then
echo "Task: $task"
docker inspect $container_id --format '{{range $net, $conf := .NetworkSettings.Networks}} {{$net}}: {{$conf.IPAddress}}{{end}}'
fi
done
# 5. 检查 DNS 解析
echo "\n5. DNS Resolution Test:"
docker run --rm --network backend alpine nslookup $service_name
# 6. 检查防火墙规则
echo "\n6. Firewall Rules:"
docker run --rm --privileged --net=host alpine iptables -L | grep -i docker
}
# 修复常见网络问题
fix_common_network_issues() {
echo "=== Fixing Common Network Issues ==="
# 1. 重启 Docker 网络服务
echo "1. Restarting Docker daemon..."
# sudo systemctl restart docker
# 2. 清理悬挂的网络
echo "2. Cleaning up dangling networks..."
docker network prune -f
# 3. 重建 ingress 网络
echo "3. Rebuilding ingress network..."
# docker network rm ingress
# docker network create --driver overlay --ingress --subnet=10.255.0.0/16 --gateway=10.255.0.1 ingress
# 4. 重启有问题的服务
echo "4. Force updating problematic services..."
for service in $(docker service ls --format '{{.Name}}'); do
failed_tasks=$(docker service ps $service --filter current-state=failed | wc -l)
if [ $failed_tasks -gt 0 ]; then
echo " Force updating service: $service"
docker service update --force $service
fi
done
# 5. 检查节点连通性
echo "5. Checking node connectivity..."
for node in $(docker node ls --format '{{.Hostname}}'); do
echo " Testing connectivity to $node..."
ping -c 1 -W 1 $node && echo " ✓ Reachable" || echo " ✗ Unreachable"
done
}
# 网络性能优化
optimize_network_performance() {
echo "=== Network Performance Optimization ==="
# 1. 调整 MTU 大小
echo "1. Checking MTU configuration..."
docker run --rm --net=host alpine ip link show | grep mtu
# 2. 优化网络缓冲区
echo "2. Network buffer optimization suggestions:"
echo " - Increase net.core.rmem_max"
echo " - Increase net.core.wmem_max"
echo " - Tune net.ipv4.tcp_rmem"
echo " - Tune net.ipv4.tcp_wmem"
# 3. 检查网络加密开销
echo "3. Checking network encryption overhead..."
for network in $(docker network ls --filter driver=overlay --format '{{.Name}}'); do
encrypted=$(docker network inspect $network --format '{{.Options.encrypted}}')
echo " $network: encrypted=$encrypted"
done
# 4. 建议网络拓扑优化
echo "4. Network topology optimization suggestions:"
echo " - Minimize cross-AZ traffic"
echo " - Use placement preferences for locality"
echo " - Consider dedicated networks for high-throughput services"
}
# 使用示例
if [ "$1" = "diagnose" ] && [ -n "$2" ]; then
diagnose_network_issues $2
elif [ "$1" = "fix" ]; then
fix_common_network_issues
elif [ "$1" = "optimize" ]; then
optimize_network_performance
else
echo "Usage: $0 {diagnose <service-name>|fix|optimize}"
fi
7. 实践练习
练习 1:多层网络架构
目标:构建一个三层网络架构的 Web 应用
# 1. 创建网络
docker network create --driver overlay --opt encrypted frontend
docker network create --driver overlay --opt encrypted backend
docker network create --driver overlay --opt encrypted database
# 2. 部署数据库层
docker service create --name mysql \
--network database \
--env MYSQL_ROOT_PASSWORD=rootpass \
--env MYSQL_DATABASE=webapp \
mysql:8.0
# 3. 部署应用层
docker service create --name api \
--network backend \
--network database \
--replicas 2 \
--env DB_HOST=mysql \
my-api:latest
# 4. 部署前端层
docker service create --name web \
--network frontend \
--network backend \
--publish 80:80 \
--replicas 3 \
nginx:alpine
# 5. 验证网络隔离
docker run --rm --network frontend alpine ping -c 1 mysql # 应该失败
docker run --rm --network backend alpine ping -c 1 mysql # 应该成功
练习 2:服务发现测试
目标:测试和验证服务发现机制
# 1. 创建测试网络
docker network create --driver overlay test-discovery
# 2. 创建多个服务
docker service create --name service-a --network test-discovery --replicas 2 alpine sleep 3600
docker service create --name service-b --network test-discovery --replicas 3 alpine sleep 3600
docker service create --name service-c --network test-discovery --replicas 1 alpine sleep 3600
# 3. 测试 DNS 解析
docker run --rm --network test-discovery alpine nslookup service-a
docker run --rm --network test-discovery alpine nslookup service-b
docker run --rm --network test-discovery alpine nslookup service-c
# 4. 测试负载均衡
for i in {1..10}; do
docker run --rm --network test-discovery alpine ping -c 1 service-b
done
# 5. 清理
docker service rm service-a service-b service-c
docker network rm test-discovery
练习 3:网络性能测试
目标:比较不同网络配置的性能
# 1. 创建不同类型的网络
docker network create --driver overlay normal-network
docker network create --driver overlay --opt encrypted encrypted-network
# 2. 部署性能测试服务
docker service create --name perf-server-normal \
--network normal-network \
--publish 8080:8080 \
my-perf-server:latest
docker service create --name perf-server-encrypted \
--network encrypted-network \
--publish 8081:8080 \
my-perf-server:latest
# 3. 运行性能测试
echo "Testing normal network:"
ab -n 1000 -c 10 http://localhost:8080/
echo "Testing encrypted network:"
ab -n 1000 -c 10 http://localhost:8081/
# 4. 比较结果并清理
docker service rm perf-server-normal perf-server-encrypted
docker network rm normal-network encrypted-network
8. 本章总结
关键要点
网络架构
- 理解 Swarm 网络组件和 VXLAN 原理
- 掌握不同网络驱动的特性和适用场景
- 学会设计多层网络架构
Overlay 网络
- 创建和配置跨主机网络
- 实现网络加密和安全隔离
- 管理网络连接和别名
服务发现
- 内置 DNS 服务发现机制
- VIP 和 DNSRR 模式的区别
- 外部服务发现集成
负载均衡
- 路由网格的工作原理
- 内置和外部负载均衡配置
- 负载均衡监控和优化
网络安全
- 网络加密和证书管理
- 微分段和访问控制
- 网络策略实现
最佳实践
- 网络设计:采用分层网络架构,实现适当的隔离
- 安全优先:启用网络加密,实施最小权限原则
- 性能优化:合理配置 MTU,避免不必要的加密开销
- 监控告警:建立网络监控和故障检测机制
- 文档记录:详细记录网络拓扑和配置
下一步学习
在下一章中,我们将学习存储管理,包括:
- 卷和绑定挂载
- 存储驱动和插件
- 数据持久化策略
- 存储性能优化
检查清单: - [ ] 理解 Swarm 网络架构 - [ ] 掌握 Overlay 网络创建和配置 - [ ] 学会服务发现和负载均衡 - [ ] 实现网络安全和隔离 - [ ] 建立网络监控和故障排除机制