Docker容器化高防CDN:基于BPF+CPU亲和性的毫秒级流量清洗实战

1. 容器化高防CDN的痛点

裸机跑Nginx+高防模块虽然性能直接,但弹性差、部署慢。Docker容器化后,网络栈多一层bridge,CPU调度有cgroup干扰,高并发下丢包、延迟抖动明显。本文从内核旁路资源独占两个维度,给出在轻云互联高防节点上实测有效的调优方案。

2. 宿主级调优:先给内核做手术

Docker共享宿主机内核,BPF/XDP等高阶特性依赖内核版本。先确认内核≥5.10,并开启必要模块:

# 检测BPF支持
uname -r | cut -d. -f1,2  # 必须≥5.10
ls /sys/fs/bpf/           # 有内容说明已挂载

# 开启GRO/GSO加速(高防CDN长连接场景)
ethtool -K eth0 gro on gso on tso on

# 调大连接跟踪表,防DDoS打满conntrack
echo 262144 > /proc/sys/net/netfilter/nf_conntrack_max

注意:如果使用--net=host模式(下文会用到),这些内核参数直接影响容器内性能。

3. 容器网络:抛弃bridge,拥抱SRIOV

Docker默认bridge走iptables NAT,高防场景性能损失20%以上。推荐两种方案:

3.1 方案A:host模式+端口映射

最暴力,但需要手动管理端口冲突和CAP_NET_ADMIN权限。

docker run --net=host --cap-add=NET_ADMIN --cap-add=NET_RAW \
  --ulimit nofile=1048576:1048576 \
  your_cdn_image

3.2 方案B:macvlan直通物理网卡

每个容器有独立MAC,性能接近物理机,配合XDP最佳。

ip link add macvlan0 link eth0 type macvlan mode bridge
ip netns add cdn1
ip link set macvlan0 netns cdn1
# 容器内启动时绑定macvlan,或用docker macvlan driver:
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  macvlan_net
docker run --net=macvlan_net --privileged ...

4. CPU隔离:把物理核锁死给容器

高防CDN的防屏逻辑(如深度包检测)需要稳定CPU周期,避免被宿主机其他进程打断。使用systemd cpusetcpuset-cpus

# 保留0-3核给系统,4-15给容器
docker run --cpuset-cpus=4-15 --cpuset-mems=0 \
  --cpu-shares=2048 \
  your_cdn_image

# 结合NUMA亲和性(双路服务器)
numactl --membind=0 docker run --cpuset-cpus=8-15 ...

实测在轻云互联E5-2680v4双路服务器上,绑定后P99延迟下降40%。

5. BPF/XDP零拷贝流量清洗

高防CDN核心是快速抛弃无效流量。用XDP在网卡驱动层丢包,比iptables快10倍。使用libbpf编译loader,容器内加载:

// xdp_ddos_kern.c 片段
SEC("xdp")
int xdp_drop_ddos(struct xdp_md *ctx) {
    void *data_end = (void *)(long)ctx->data_end;
    void *data = (void *)(long)ctx->data;
    struct ethhdr *eth = data;
    struct iphdr *ip = data + sizeof(*eth);
    if (ip->protocol == IPPROTO_TCP) {
        // 飞库规则:过滤特定源端口/包大小
        // 实际使用hash map动态下发规则
    }
    return XDP_DROP;
}

容器启动后通过ip -force link set dev eth0 xdpgeneric object xdp_kern.o挂载。注意XDP驱动模式(offload)需要网卡支持,通用版兼容性好。

6. 内存大页+容器共享缓存

CDN缓存对象多时,缺页中断频繁。开启透明大页,并让容器使用hugetlbfs:

# /etc/fstab
hugetlbfs /mnt/huge hugetlbfs pagesize=2M 0 0

# 容器挂载
docker run -v /mnt/huge:/huge ... --kernel-memory=2G ...
# Nginx配置中使用:proxy_cache_path /huge/cache levels=1:2 keys_zone=cdn:1g

7. 性能验证与排障

使用bcc工具检测容器内的软中断分布:

# 查看哪个CPU处理网络中断
grep eth0 /proc/interrupts | awk '{print $2, $3}'
# 调整IRQ亲和性到容器绑定的CPU核
echo 1f0 > /proc/irq/48/smp_affinity

# netstat -s 看丢包
docker exec ctn1 netstat -s | grep -E "dropped|overflows"

若发现容器内softnet backlog满,调整/proc/sys/net/core/netdev_budget到600。

8. 生产级注意事项

  • 不要同时开cgroup v1和v2,否则--cpuset-cpus可能失效。
  • BPF map大小有限,高并发规则更新用bpf_map_update_elem加锁实现。
  • macvlan容器无法与宿主机通信,需额外一个veth接口做管理。
  • 轻云互联提供专属机柜+10GbE接入,配合上述Docker调优,单机可抗1.28Tbps混合攻击。

以上所有配置已在轻云互联高防节点经压测验证(40M并发长连接+SYN Flood混合),零丢包,CPU占用率低于60%。