学习目标

通过本章学习,您将能够:

  • 理解 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. 本章总结

关键要点

  1. 网络架构

    • 理解 Swarm 网络组件和 VXLAN 原理
    • 掌握不同网络驱动的特性和适用场景
    • 学会设计多层网络架构
  2. Overlay 网络

    • 创建和配置跨主机网络
    • 实现网络加密和安全隔离
    • 管理网络连接和别名
  3. 服务发现

    • 内置 DNS 服务发现机制
    • VIP 和 DNSRR 模式的区别
    • 外部服务发现集成
  4. 负载均衡

    • 路由网格的工作原理
    • 内置和外部负载均衡配置
    • 负载均衡监控和优化
  5. 网络安全

    • 网络加密和证书管理
    • 微分段和访问控制
    • 网络策略实现

最佳实践

  1. 网络设计:采用分层网络架构,实现适当的隔离
  2. 安全优先:启用网络加密,实施最小权限原则
  3. 性能优化:合理配置 MTU,避免不必要的加密开销
  4. 监控告警:建立网络监控和故障检测机制
  5. 文档记录:详细记录网络拓扑和配置

下一步学习

在下一章中,我们将学习存储管理,包括:

  • 卷和绑定挂载
  • 存储驱动和插件
  • 数据持久化策略
  • 存储性能优化

检查清单: - [ ] 理解 Swarm 网络架构 - [ ] 掌握 Overlay 网络创建和配置 - [ ] 学会服务发现和负载均衡 - [ ] 实现网络安全和隔离 - [ ] 建立网络监控和故障排除机制