Files
docker_practice/09_network/9.7_advanced_networking.md
2026-03-05 19:39:42 -08:00

14 KiB
Raw Blame History

9.7 容器网络高级特性

深入探讨容器网络的核心机制、Overlay 网络、CNI 插件生态、容器 DNS 解析、网络策略等高级特性,为生产级别的网络架构打下坚实基础。

9.7.1 Overlay 网络原理与配置

Overlay 网络在现有网络基础上建立虚拟网络,允许容器跨宿主机通信。它是 Kubernetes 和 Swarm 模式的基础。

Overlay 网络工作原理

Overlay 网络通过隧道封装技术(通常是 VXLAN将容器网络流量封装在宿主机物理网络的 UDP 数据包中传输。

容器 A (192.168.0.2)
    ↓
veth 对
    ↓
br-net (网桥)
    ↓
Docker 引擎 (VXLAN 封装)
    ↓
物理网络 (172.16.0.0/24)
    ↓
Docker 引擎 (VXLAN 解封装)
    ↓
br-net (网桥)
    ↓
veth 对
    ↓
容器 B (192.168.0.3,不同宿主机)

创建和使用 Overlay 网络

Docker Swarm 模式下的 Overlay 网络:

# 初始化 Swarm创建集群
docker swarm init

# 创建 overlay 网络
docker network create --driver overlay \
  --subnet 192.168.0.0/24 \
  --opt com.docker.network.driver.mtu=1450 \
  my-overlay-net

# 验证网络创建
docker network ls
docker network inspect my-overlay-net

# 在 Swarm 服务中使用 overlay 网络
docker service create --name web \
  --network my-overlay-net \
  --replicas 3 \
  nginx:latest

# 验证服务跨节点通信
docker service ps web

单机 Overlay 网络模拟Linux 容器):

# 创建自定义 overlay 网络
docker network create --driver overlay custom-overlay

# 创建两个容器
docker run -d --name container1 --network custom-overlay nginx:latest
docker run -d --name container2 --network custom-overlay nginx:latest

# 测试跨容器通信
docker exec container1 ping container2
docker exec container1 curl http://container2

# 检查网络配置
docker network inspect custom-overlay

Overlay 网络性能优化

# 调整 MTUMaximum Transmission Unit避免分片
# VXLAN 开销 50 字节,物理 MTU 1500建议设置为 1450
docker network create --driver overlay \
  --opt com.docker.network.driver.mtu=1450 \
  optimized-overlay

# 启用 IP 地址管理IPAM自定义
docker network create --driver overlay \
  --subnet 10.0.9.0/24 \
  --aux-address "my-router=10.0.9.2" \
  my-custom-overlay

# 在 Compose 中使用 overlay 网络
version: '3.9'
services:
  web:
    image: nginx
    networks:
      - backend

  db:
    image: postgres
    networks:
      - backend

networks:
  backend:
    driver: overlay
    driver_opts:
      com.docker.network.driver.mtu: 1450

9.7.2 CNI 插件生态概览

容器网络接口CNI是容器编排平台尤其是 Kubernetes的标准化网络接口。不同的 CNI 插件提供不同的网络能力。

主流 CNI 插件对比

Calico - 基于 BGP 的网络

Calico 使用 BGP 协议进行路由,支持网络策略和 eBPF 加速。

# Kubernetes 中安装 Calico
apiVersion: v1
kind: ConfigMap
metadata:
  name: calico-config
  namespace: kube-system
data:
  cni_network_config: |
    {
      "name": "k8s-pod-network",
      "cniVersion": "0.4.0",
      "plugins": [
        {
          "type": "calico",
          "datastore_type": "kubernetes",
          "mtu": 1450,
          "ipam": {
            "type": "calico-ipam"
          }
        },
        {
          "type": "portmap",
          "snat": true,
          "capabilities": {"portMappings": true}
        }
      ]
    }

Flannel - 简单可靠的 Overlay

Flannel 提供简单的 overlay 网络实现,适合小到中等规模的集群。

# 安装 Flannel
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

# 配置 Flannel 后端VXLAN、UDP、AWS VPC 等)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-flannel-cfg
  namespace: kube-flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
EOF

Cilium - eBPF 驱动的先进网络

Cilium 使用 eBPF 在内核级别实现网络策略和可观测性,性能优异。

# 安装 Cilium
helm repo add cilium https://helm.cilium.io
helm install cilium cilium/cilium \
  --namespace kube-system \
  --set image.tag=v1.14.0 \
  --set operator.replicas=1

# 启用 Hubble可观测性
helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --reuse-values \
  --set hubble.enabled=true \
  --set hubble.ui.enabled=true

Weave - 跨主机网络通信

Weave 提供简单的跨主机通信,支持加密和多播。

# Docker 中使用 Weave 网络
docker run -d --name weave \
  --net=host \
  --cap-add=NET_ADMIN \
  --cap-add=SYS_PTRACE \
  ghcr.io/weaveworks/weave:latest

# 连接到 Weave 网络
docker run -d --network weave --name web nginx:latest

CNI 插件对比表:

特性 Calico Flannel Cilium Weave
路由方式 BGP VXLAN/UDP eBPF VxLAN
网络策略 ✓ (L3-L7)
性能
可观测性
学习曲线
生产就绪

9.7.3 容器 DNS 解析机制

Docker 内置 DNS 服务器,但 DNS 解析涉及多个层面的配置。

DNS 解析流程

容器应用 (dig www.example.com)
    ↓
容器内 /etc/resolv.conf (127.0.0.11:53)
    ↓
Docker 内嵌 DNS 服务器 (127.0.0.11)
    ↓
用户自定义 DNS 或宿主机 /etc/resolv.conf
    ↓
外部 DNS 服务器 (8.8.8.8 等)
    ↓
DNS 响应 → 容器缓存 → 应用

配置容器 DNS

在运行时指定 DNS

# 单个容器
docker run -d \
  --dns 8.8.8.8 \
  --dns 1.1.1.1 \
  --dns-search example.com \
  nginx:latest

# DNS 选项
docker run -d \
  --dns-option ndots:2 \
  --dns-option timeout:1 \
  --dns-option attempts:3 \
  nginx:latest

# 查看容器 DNS 配置
docker exec <container_id> cat /etc/resolv.conf

Docker Compose DNS 配置:

version: '3.9'

services:
  web:
    image: nginx
    dns:
      - 8.8.8.8
      - 1.1.1.1
    dns_search:
      - example.com
      - local

  db:
    image: postgres
    networks:
      - backend
    hostname: postgres-db

networks:
  backend:
    driver: bridge

# 容器内 /etc/resolv.conf 将被自动配置
# search example.com local
# nameserver 8.8.8.8
# nameserver 1.1.1.1

Docker 守护进程级别配置:

{
  "dns": ["8.8.8.8", "1.1.1.1"],
  "dns-search": ["example.com"],
  "insecure-registries": [],
  "registry-mirrors": ["https://mirror.example.com"]
}

自定义服务发现Service Discovery

使用 Docker 内建 DNS 的服务发现:

# 创建自定义网络
docker network create mynet

# 运行服务
docker run -d --name web --network mynet nginx:latest
docker run -d --name db --network mynet postgres:latest

# 在其他容器中通过服务名访问
docker run -it --network mynet busybox sh
# ping web  # 自动解析到 web 容器 IP
# ping db   # 自动解析到 db 容器 IP

Compose 服务名自动发现:

version: '3.9'

services:
  frontend:
    image: nginx
    depends_on:
      - backend
    environment:
      BACKEND_URL: http://backend:8080

  backend:
    image: myapp
    depends_on:
      - database

  database:
    image: postgres
    environment:
      POSTGRES_DB: mydb

# frontend 容器可以直接访问 http://backend:8080
# backend 容器可以直接访问 postgres://database:5432

DNS 性能优化

# 检查 DNS 延迟
time docker exec <container> nslookup www.example.com

# 优化 DNS 解析
docker run -d \
  --dns 127.0.0.1 \  # 使用本地缓存 DNS (Dnsmasq)
  nginx:latest

# 在 Kubernetes 中优化
kubectl patch deployment -n kube-system coredns --patch '{
  "spec": {
    "template": {
      "spec": {
        "containers": [
          {
            "name": "coredns",
            "resources": {
              "limits": {
                "memory": "512Mi",
                "cpu": "500m"
              }
            }
          }
        ]
      }
    }
  }
}'

9.7.4 网络策略NetworkPolicy实践

网络策略定义了容器间的流量控制规则,是微服务架构中的安全基础。

基本网络策略

默认拒绝所有入站流量的策略:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  # 不指定 ingress 规则,表示拒绝所有入站流量

允许特定来源的入站流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-frontend
spec:
  podSelector:
    matchLabels:
      tier: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tier: frontend
    ports:
    - protocol: TCP
      port: 8080

允许出站流量到数据库:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-backend-to-db
spec:
  podSelector:
    matchLabels:
      tier: backend
  policyTypes:
  - Egress
  egress:
  # 允许到数据库的流量
  - to:
    - podSelector:
        matchLabels:
          tier: database
    ports:
    - protocol: TCP
      port: 5432
  # 允许 DNS 查询
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
  # 允许到外部 API 的流量
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 169.254.169.254/32  # 阻止元数据服务
    ports:
    - protocol: TCP
      port: 443

微服务网络策略示例

---
# 拒绝所有默认
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

---
# Frontend 容器策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  # 允许来自 Ingress Controller 的流量
  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-nginx
    - podSelector:
        matchLabels:
          app: ingress-controller
    ports:
    - protocol: TCP
      port: 3000
  egress:
  # 允许到 API 的流量
  - to:
    - podSelector:
        matchLabels:
          app: api
    ports:
    - protocol: TCP
      port: 8080
  # 允许 DNS
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

---
# API 容器策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080
  egress:
  # 允许到数据库的流量
  - to:
    - podSelector:
        matchLabels:
          app: postgres
    ports:
    - protocol: TCP
      port: 5432
  # 允许 DNS
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53

---
# 数据库容器策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-postgres
spec:
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: api
    ports:
    - protocol: TCP
      port: 5432

使用 Calico/Cilium 的高级网络策略

L7 应用层策略(仅 Cilium 支持):

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "api-gateway-policy"
spec:
  description: "L7 policy for API gateway"
  endpointSelector:
    matchLabels:
      app: api
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: frontend
    toPorts:
    - ports:
      - port: "8080"
        protocol: TCP
      rules:
        http:
        # 允许 GET /api/users
        - method: "GET"
          path: "/api/users/.*"
        # 允许 POST /api/users 仅从管理员来源
        - method: "POST"
          path: "/api/users"
          sourceIPs:
          - "10.0.0.0/8"

9.7.5 跨主机容器通信方案对比

方案对比表

方案 隔离性 性能 复杂度 适用场景
主机网络 高性能,单主机
Bridge + Host Port 小规模集群
Overlay (VXLAN) 跨域通信
BGP (Calico) 大规模集群
eBPF (Cilium) 高性能大集群

选择建议

# 1. 开发环境:使用 Bridge 网络
docker network create my-app
docker-compose up  # 默认使用 bridge

# 2. 小规模生产(< 50 节点):使用 Flannel
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

# 3. 中等规模50-500 节点):使用 Calico
kubeadm init --pod-network-cidr=192.168.0.0/16
kubectl apply -f https://docs.projectcalico.org/v3.24/manifests/tigera-operator.yaml

# 4. 大规模(> 500 节点)或需要 L7 策略:使用 Cilium
helm install cilium cilium/cilium --namespace kube-system

# 5. 需要多云/跨域:使用 Weave

9.7.6 网络故障排查

常见网络问题诊断:

# 1. 容器无法访问外部网络
docker exec <container> ping 8.8.8.8
docker exec <container> cat /etc/resolv.conf
docker logs <container> | grep -i network

# 2. 容器间无法通信
docker network inspect <network>
docker exec <container1> ping <container2>

# 3. 端口映射失效
docker port <container>
netstat -tlnp | grep <port>

# 4. DNS 解析失败
docker exec <container> nslookup example.com
docker exec <container> cat /etc/hosts

# 5. 网络延迟
docker run --rm --network host iperf3:latest -c <target>
docker exec <container> mtr -r example.com

# 使用 tcpdump 抓包分析
docker run --rm --cap-add NET_ADMIN --network host \
  corfr/tcpdump -i eth0 -n "port 80"