0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于eBPF的Kubernetes网络异常检测系统

马哥Linux运维 来源:马哥Linux运维 2025-07-24 14:09 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

前言:为什么选择 eBPF?

作为一名在云原生领域深耕多年的运维工程师,我见过太多因为网络问题导致的生产事故。传统的监控手段往往是事后诸葛亮,当你发现问题时,用户已经在抱怨了。今天,我将分享如何利用 eBPF 这一革命性技术,构建一套能够实时检测 Kubernetes 网络异常的系统。

痛点分析:传统网络监控的困境

在 Kubernetes 环境中,网络问题往往具有以下特点:

复杂性高:Pod 间通信涉及 CNI、Service Mesh、负载均衡器等多个组件
排查困难:问题发生时往往已经影响用户,缺乏实时的深度观测能力
成本昂贵:传统 APM 工具价格不菲,且对内核级别的网络事件监控有限

而 eBPF 的出现,让我们有了在内核空间进行无侵入式监控的能力。

系统架构设计

我们的系统采用分层架构,主要包含以下组件:

┌─────────────────────────────────────────────────────────┐
│          Web Dashboard            │
├─────────────────────────────────────────────────────────┤
│          Alert Manager            │
├─────────────────────────────────────────────────────────┤
│         Data Processor             │
├─────────────────────────────────────────────────────────┤
│         eBPF Data Collector          │
├─────────────────────────────────────────────────────────┤
│          Kernel Space             │
└─────────────────────────────────────────────────────────┘

核心实现:eBPF 程序开发

1. TCP 连接异常检测

首先,我们需要编写 eBPF 程序来监控 TCP 连接状态:

// tcp_monitor.bpf.c
#include
#include
#include
#include

structtcp_event{
  __u32 pid;
  __u32 saddr;
  __u32 daddr;
  __u16 sport;
  __u16 dport;
  __u8 state;
  __u64 timestamp;
};

struct{
  __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
  __uint(key_size,sizeof(__u32));
  __uint(value_size,sizeof(__u32));
} tcp_eventsSEC(".maps");

SEC("kprobe/tcp_set_state")
inttrace_tcp_state_change(structpt_regs *ctx){
 structsock*sk=(structsock *)PT_REGS_PARM1(ctx);
 intnew_state = PT_REGS_PARM2(ctx);
 
 structtcp_eventevent={};
  event.timestamp = bpf_ktime_get_ns();
  event.pid = bpf_get_current_pid_tgid() >>32;
  event.state = new_state;
 
 // 获取连接信息
  BPF_CORE_READ_INTO(&event.saddr, sk, __sk_common.skc_rcv_saddr);
  BPF_CORE_READ_INTO(&event.daddr, sk, __sk_common.skc_daddr);
  BPF_CORE_READ_INTO(&event.sport, sk, __sk_common.skc_num);
  BPF_CORE_READ_INTO(&event.dport, sk, __sk_common.skc_dport);
 
 // 只关注异常状态变化
 if(new_state == TCP_CLOSE || new_state == TCP_TIME_WAIT) {
    bpf_perf_event_output(ctx, &tcp_events, BPF_F_CURRENT_CPU,
              &event,sizeof(event));
  }
 
 return0;
}

charLICENSE[] SEC("license") ="GPL";

2. Go 用户空间程序

接下来实现用户空间的数据收集器:

// main.go
packagemain

import(
 "bytes"
 "encoding/binary"
 "fmt"
 "log"
 "net"
 "time"
 
 "github.com/cilium/ebpf"
 "github.com/cilium/ebpf/link"
 "github.com/cilium/ebpf/perf"
 "github.com/cilium/ebpf/rlimit"
)

typeTCPEventstruct{
  PID   uint32
  SrcAddr uint32
  DstAddr uint32
  SrcPort uint16
  DstPort uint16
  State  uint8
  Timestampuint64
}

typeNetworkMonitorstruct{
  collection *ebpf.Collection
  reader   *perf.Reader
  links   []link.Link
}

funcNewNetworkMonitor()(*NetworkMonitor,error) {
 // 移除内存限制
 iferr := rlimit.RemoveMemlock(); err !=nil{
   returnnil, fmt.Errorf("remove memlock: %w", err)
  }
 
 // 加载 eBPF 程序
  collection, err := ebpf.NewCollectionFromFile("tcp_monitor.o")
 iferr !=nil{
   returnnil, fmt.Errorf("load eBPF program: %w", err)
  }
 
 // 附加到内核探针
  kprobe, err := link.Kprobe(link.KprobeOptions{
    Symbol:"tcp_set_state",
    Program: collection.Programs["trace_tcp_state_change"],
  })
 iferr !=nil{
   returnnil, fmt.Errorf("attach kprobe: %w", err)
  }
 
 // 创建 perf 事件读取器
  reader, err := perf.NewReader(collection.Maps["tcp_events"],4096)
 iferr !=nil{
   returnnil, fmt.Errorf("create perf reader: %w", err)
  }
 
 return&NetworkMonitor{
    collection: collection,
    reader:   reader,
    links:   []link.Link{kprobe},
  },nil
}

func(nm *NetworkMonitor)Start()error{
  log.Println("开始监控 TCP 连接状态变化...")
 
 for{
    record, err := nm.reader.Read()
   iferr !=nil{
     returnfmt.Errorf("read perf event: %w", err)
    }
   
   varevent TCPEvent
   iferr := binary.Read(bytes.NewReader(record.RawSample),
              binary.LittleEndian, &event); err !=nil{
     continue
    }
   
    nm.processEvent(&event)
  }
}

func(nm *NetworkMonitor)processEvent(event *TCPEvent) {
  srcIP := intToIP(event.SrcAddr)
  dstIP := intToIP(event.DstAddr)
 
 // 异常检测逻辑
 ifevent.State ==7{// TCP_CLOSE
    log.Printf("检测到连接关闭: %s:%d -> %s:%d (PID: %d)",
         srcIP, event.SrcPort, dstIP, event.DstPort, event.PID)
   
   // 判断是否为异常关闭
   ifnm.isAbnormalClose(event) {
      nm.triggerAlert(event)
    }
  }
}

func(nm *NetworkMonitor)isAbnormalClose(event *TCPEvent)bool{
 // 实现异常检测算法
 // 这里可以加入机器学习模型或规则引擎
 
 // 示例:检测短时间内大量连接关闭
 returnnm.checkConnectionFlood(event)
}

func(nm *NetworkMonitor)checkConnectionFlood(event *TCPEvent)bool{
 // 简化版本:检测是否在短时间内有过多连接关闭
 // 实际实现中应该使用时间窗口和阈值算法
 returnfalse
}

func(nm *NetworkMonitor)triggerAlert(event *TCPEvent) {
  alert := Alert{
    Type:   "connection_abnormal",
    Severity: "warning",
    Message:  fmt.Sprintf("检测到异常连接关闭: PID %d", event.PID),
    Timestamp: time.Now(),
    Metadata:map[string]interface{}{
     "src_ip":  intToIP(event.SrcAddr).String(),
     "dst_ip":  intToIP(event.DstAddr).String(),
     "src_port": event.SrcPort,
     "dst_port": event.DstPort,
    },
  }
 
 // 发送告警
  nm.sendAlert(alert)
}

funcintToIP(addruint32)net.IP {
  ip :=make(net.IP,4)
  binary.LittleEndian.PutUint32(ip, addr)
 returnip
}

在 Kubernetes 中部署

1. 创建 DaemonSet

我们需要在每个节点上运行监控程序:

# k8s-deployment.yaml
apiVersion:apps/v1
kind:DaemonSet
metadata:
name:ebpf-network-monitor
namespace:monitoring
spec:
selector:
 matchLabels:
  app:ebpf-network-monitor
template:
 metadata:
  labels:
   app:ebpf-network-monitor
 spec:
  hostNetwork:true
  hostPID:true
  containers:
  -name:monitor
   image:ebpf-network-monitor:latest
   securityContext:
    privileged:true
   volumeMounts:
   -name:sys-kernel-debug
    mountPath:/sys/kernel/debug
   -name:lib-modules
    mountPath:/lib/modules
   -name:usr-src
    mountPath:/usr/src
   env:
   -name:NODE_NAME
    valueFrom:
     fieldRef:
      fieldPath:spec.nodeName
  volumes:
  -name:sys-kernel-debug
   hostPath:
    path:/sys/kernel/debug
  -name:lib-modules
   hostPath:
    path:/lib/modules
  -name:usr-src
   hostPath:
    path:/usr/src
  serviceAccount:ebpf-monitor
---
apiVersion:v1
kind:ServiceAccount
metadata:
name:ebpf-monitor
namespace:monitoring
---
apiVersion:rbac.authorization.k8s.io/v1
kind:ClusterRole
metadata:
name:ebpf-monitor
rules:
-apiGroups:[""]
resources:["pods","nodes"]
verbs:["get","list","watch"]
---
apiVersion:rbac.authorization.k8s.io/v1
kind:ClusterRoleBinding
metadata:
name:ebpf-monitor
roleRef:
apiGroup:rbac.authorization.k8s.io
kind:ClusterRole
name:ebpf-monitor
subjects:
-kind:ServiceAccount
name:ebpf-monitor
namespace:monitoring

2. 添加网络策略检测

扩展我们的 eBPF 程序来监控网络策略违规:

// network_policy.bpf.c
SEC("kprobe/ip_rcv")
inttrace_packet_receive(structpt_regs *ctx){
 structsk_buff*skb=(structsk_buff *)PT_REGS_PARM1(ctx);
 structiphdr*ip;
 
 // 读取 IP 头
  bpf_probe_read(&ip,sizeof(structiphdr),
         skb->data +sizeof(structethhdr));
 
 // 检查是否违反网络策略
 if(is_policy_violation(ip)) {
   structpolicy_eventevent={
      .src_ip = ip->saddr,
      .dst_ip = ip->daddr,
      .protocol = ip->protocol,
      .timestamp = bpf_ktime_get_ns(),
    };
   
    bpf_perf_event_output(ctx, &policy_events, BPF_F_CURRENT_CPU,
              &event,sizeof(event));
  }
 
 return0;
}

实战优化技巧

1. 性能优化

// 使用批量处理减少系统调用
typeEventBatcherstruct{
  events []TCPEvent
  mutex sync.Mutex
  timer *time.Timer
}

func(eb *EventBatcher)AddEvent(event TCPEvent) {
  eb.mutex.Lock()
 defereb.mutex.Unlock()
 
  eb.events =append(eb.events, event)
 
 // 批量大小达到阈值或定时器触发时处理
 iflen(eb.events) >=100{
    eb.flush()
  }elseifeb.timer ==nil{
    eb.timer = time.AfterFunc(100*time.Millisecond, eb.flush)
  }
}

func(eb *EventBatcher)flush() {
  eb.mutex.Lock()
  events := eb.events
  eb.events =nil
  eb.timer =nil
  eb.mutex.Unlock()
 
 // 批量处理事件
 for_, event :=rangeevents {
    processEvent(&event)
  }
}

2. 智能异常检测

// 基于统计的异常检测
typeAnomalyDetectorstruct{
  connectionsmap[string]*ConnectionStats
  mutex   sync.RWMutex
}

typeConnectionStatsstruct{
  Count  int64
  LastSeen time.Time
  Failures int64
  AvgLatencyfloat64
}

func(ad *AnomalyDetector)DetectAnomaly(event *TCPEvent)bool{
  key := fmt.Sprintf("%s:%d->%s:%d",
           intToIP(event.SrcAddr), event.SrcPort,
           intToIP(event.DstAddr), event.DstPort)
 
  ad.mutex.RLock()
  stats, exists := ad.connections[key]
  ad.mutex.RUnlock()
 
 if!exists {
    stats = &ConnectionStats{}
    ad.mutex.Lock()
    ad.connections[key] = stats
    ad.mutex.Unlock()
  }
 
 // 更新统计信息
  stats.Count++
  stats.LastSeen = time.Now()
 
 // 异常检测算法
 ifevent.State == TCP_CLOSE {
    stats.Failures++
    failureRate :=float64(stats.Failures) /float64(stats.Count)
   
   // 如果失败率超过阈值,认为是异常
   returnfailureRate >0.1&& stats.Count >10
  }
 
 returnfalse
}

告警与可视化

1. Prometheus 集成

// metrics.go
packagemain

import(
 "github.com/prometheus/client_golang/prometheus"
 "github.com/prometheus/client_golang/prometheus/promauto"
)

var(
  tcpConnectionsTotal = promauto.NewCounterVec(
    prometheus.CounterOpts{
      Name:"tcp_connections_total",
      Help:"Total number of TCP connections",
    },
    []string{"src_ip","dst_ip","state"},
  )
 
  networkAnomaliesTotal = promauto.NewCounterVec(
    prometheus.CounterOpts{
      Name:"network_anomalies_total",
      Help:"Total number of network anomalies detected",
    },
    []string{"type","severity"},
  )
)

funcupdateMetrics(event *TCPEvent){
  tcpConnectionsTotal.WithLabelValues(
    intToIP(event.SrcAddr).String(),
    intToIP(event.DstAddr).String(),
    tcpStateToString(event.State),
  ).Inc()
 
 ifisAnomalous(event) {
    networkAnomaliesTotal.WithLabelValues(
     "connection_anomaly",
     "warning",
    ).Inc()
  }
}

2. Grafana 仪表板配置

{
"dashboard":{
 "title":"eBPF Network Monitoring",
 "panels":[
  {
   "title":"TCP Connection States",
   "type":"stat",
   "targets":[
    {
     "expr":"rate(tcp_connections_total[5m])",
     "legendFormat":"{{state}}"
    }
   ]
  },
  {
   "title":"Network Anomalies",
   "type":"graph",
   "targets":[
    {
     "expr":"increase(network_anomalies_total[1h])",
     "legendFormat":"{{type}}"
    }
   ]
  }
 ]
}
}

实际效果与案例

经过在生产环境的部署测试,我们的系统成功检测到了多种网络异常:

DNS 解析异常:检测到某个 Pod 频繁进行 DNS 查询但响应缓慢
连接池耗尽:及时发现微服务之间的连接数异常增长
网络分区:在节点网络出现问题时第一时间告警

相比传统监控方案,我们的系统具有以下优势:

零侵入:无需修改应用代码或配置

实时性:内核级别的监控,延迟极低

全面性:覆盖 L3/L4 层的所有网络事件

成本低:开源方案,无license费用

总结与展望

通过 eBPF 技术,我们成功构建了一套强大的 Kubernetes 网络异常检测系统。这套系统不仅解决了传统监控的痛点,还为我们提供了前所未有的网络可观测性。

下一步计划

1. 集成机器学习算法,提升异常检测准确率

2. 增加更多协议支持(HTTP/2、gRPC等)

3. 开发自动修复能力,实现真正的自愈系统

如果你也在为 Kubernetes 网络问题头疼,不妨试试这套方案。相信它会给你带来意想不到的效果!

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 异常检测
    +关注

    关注

    1

    文章

    45

    浏览量

    9969
  • kubernetes
    +关注

    关注

    0

    文章

    256

    浏览量

    9412

原文标题:从 0 到 1 构建基于 eBPF 的 Kubernetes 网络异常检测系统

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Kubernetes 网络模型如何实现常见网络任务

    Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernete
    的头像 发表于 10-08 11:32 1572次阅读

    关于 eBPF 安全可观测性,你需要知道的那些事儿

    交互,负责采集配置和数据分析Metrics(度量)这也是可观测性与监控最主要的区别。系统中某一类信息的统计聚合,比如 CPU、内存、网络吞吐、硬盘 I/O、硬盘使用等情况。当度量值触发异常阈值时,
    发表于 09-08 15:31

    openEuler 倡议建立 eBPF 软件发布标准

    扩展到了网络、内核、安全、跟踪等,而且它的功能特性还在快速发展中,早期的 BPF 被称为经典 BPF,简称 cBPF,正是这种功能扩展,使得现在的 BPF 被称为扩展 BPF,简称 eBPF。如今
    发表于 12-23 16:21

    基于密度的异常挖掘智能网络入侵检测系统设计与实现

    论文提出了基于密度的异常挖掘新方法,并将其应用于入侵检测系统引擎设计中,构建了相应的网络入侵检测系统
    发表于 07-30 11:15 37次下载

    Kubernetes网络隔离NetworkPolicy实验

    Kubernetes的一个重要特性就是要把不同node节点的pod(container)连接起来,无视物理节点的限制。但是在某些应用环境中,比如公有云,不同租户的pod不应该互通,这个时候就需要网络
    发表于 11-28 10:00 2835次阅读

    基于健壮多元概率校准模型的全网络异常检测

    当前因特网环境下各种网络异常事件层出不穷,DDoS攻击、僵尸网络等大规模的网络入侵给互联网的安全运营带来严重威胁,而网络拥塞、
    发表于 03-06 10:02 0次下载

    单分类支持向量机和主动学习的网络异常检测

    在日益复杂的网络环境中,网络攻击越来越多样化和复杂化,新的攻击手段层出不穷。异常检测通过训练集为网络行为建立特征轮廓模型,通过计算新数据与正
    发表于 03-06 15:25 1次下载

    云模型的网络异常流量检测

    网络流量的复杂性、难以预测性以及人们主观评测的差异性等不确定因素,使得网络流量的异常检测成为网络安全防护领域研究的难点问题。通过对流量安全特
    发表于 03-06 16:44 1次下载
    云模型的<b class='flag-5'>网络</b><b class='flag-5'>异常</b>流量<b class='flag-5'>检测</b>

    大流量数据的高温度网络异常检测综述

    对包含大流量数据的高维度网络进行异常检测,必须加入维数约简处理以减轻系统在传输和存储方面的压力。介绍高速网络环境下
    发表于 05-11 15:49 4次下载

    eBPF是什么以及eBPF能干什么

    一、eBPF是什么 eBPF是extended BPF的缩写,而BPF是Berkeley Packet Filter的缩写。对linux网络比较熟悉的伙伴对BPF应该比较了解,它通过特定的语法
    的头像 发表于 07-05 15:17 1.3w次阅读
    <b class='flag-5'>eBPF</b>是什么以及<b class='flag-5'>eBPF</b>能干什么

    入门炫酷的Kubernetes网络方案

        最近业界使用范围最广的K8S CNI网络方案 Calico 宣布支持 eBPF,而作为第一个通过 eBPF 实现了 kube-proxy 所有功能的 K8S 网络方案——Cil
    的头像 发表于 10-13 15:19 1801次阅读

    Kubernetes网络模型介绍以及如何实现常见网络任务

    Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernete
    的头像 发表于 05-05 20:22 2354次阅读

    Kubernetes网络模型的基础知识

    Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernete
    的头像 发表于 07-20 09:46 1754次阅读

    Kubernetes集群发生网络异常时如何排查

    本文将引入一个思路:“在 Kubernetes 集群发生网络异常时如何排查”。文章将引入 Kubernetes 集群中网络排查的思路,包含
    的头像 发表于 09-02 09:45 9367次阅读

    工业控制系统异常检测方法的研究和应用情况

    传统的工业控制系统不同于互联网开放的体系,而是个体封闭的。但是随着工业互联网平台的应用,越来越多的设备连接到企业网络,从而引发了越来越多的网络安全问题。传统采用网络流量的方法,出现了
    发表于 10-14 11:31 2504次阅读