本文介绍利用eBPF技术无侵入地获得容器性能数据、内核Trace数据或网络指标数据等,从而快速发现目标容器和关联的Pod存在的性能问题。
背景信息
eBPF(Extended Berkeley Packet Filter)是一项运行沙箱程序的技术,允许开发者在操作系统内核内安全运行自定义代码,并即时获得执行结果,而无需修改内核源代码或加载内核模块,从而避免复杂的运维操作。
在Kubernetes生态中,eBPF的主要应用场景有:
网络管理:Cilium网络插件,可以灵活更新网络策略并实施流量转发。
故障定位与事件追踪:使用Falco等工具实时监控Kubernetes集群中容器的系统调用和访问行为,帮助运维人员及时发现安全风险。
安全监控:在入侵检测中,如端口扫描,一旦检测到异常行为,eBPF程序能够阻止数据包传输并隔离受攻击的容器,最大限度减少安全风险。
性能监控:Sysdig等工具提供性能和故障诊断,监控集群或单机的性能数据。
eBPF的运行分为用户态(User Space)和内核态(Kernel Space):
用户态:通常是用于编写和加载eBPF程序的应用程序。您可以使用如C语言等编写eBPF程序,并通过工具(如
bpftool
,libbpf
等)将其加载到内核中。内核态:eBPF程序被加载并实际执行的环境。eBPF程序在内核态中运行,可以直接访问内核数据结构和接口,进行特定的监控与处理工作。
对此,ACS提供了基于eBPF的可观测能力,您可以在Pod的/sys/kernel/debug
目录下配置监控项和指标,实现对细粒度数据的监控,帮助您优化性能和排查故障。
前置条件
已为ACS Pod开启特权模式。
ACS默认不提供开启特权模式的入口, 请提交工单申请。
应用示例
以下演示eBPF程序在实际ACS容器算力环境下的使用。本示例的镜像中使用了社区开源的Go语言框架eBPF工具软件ebpf-go,ebpf-go包含了多个示例应用。关于此示例基础镜像的详细信息,请参见相关信息。
以其中的fentry eBPF程序为例,将fentry eBPF程序加载到容器的tcp_connect上。当容器向目标发送TCP SYN数据包时,eBPF会打印出对应的命令/IP/端口信息。
使用以下YAML内容,创建名为acs-test-ebpf-demo的工作负载。具体操作,请参见创建无状态工作负载Deployment。
apiVersion: apps/v1 kind: Deployment metadata: labels: app: acs-test-ebpf-demo name: acs-test-ebpf-demo namespace: default spec: progressDeadlineSeconds: 600 replicas: 1 selector: matchLabels: app: acs-test-ebpf-demo strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: labels: alibabacloud.com/compute-class: general-purpose alibabacloud.com/compute-qos: default app: acs-test-ebpf-demo spec: containers: - command: - /bin/sh - -c - sleep 36000 image: registry-cn-hangzhou.ack.aliyuncs.com/acs/ebpf-example:v1-alpha imagePullPolicy: Always name: test-ebpf resources: requests: cpu: "2" memory: 4Gi securityContext: capabilities: add: - SYS_ADMIN - NET_ADMIN - NET_RAW - SYS_RESOURCE - SYS_PTRACE - IPC_LOCK - SYSLOG volumeMounts: - mountPath: /sys/kernel/debug name: volume-debugfs readOnly: true restartPolicy: Always volumes: - emptyDir: {} name: emptydir-volume - hostPath: path: /sys/kernel/debug type: "" name: volume-debugfs
部分配置项说明如下:
配置项
说明
.spec.template.volume.hostPath
指定需要挂载的路径。
.spec.template.container.volumeMounts
设置挂载的路径在容器内的目标路径。
.spec.template.container.securityContext.capabilities.add
设置挂载的eBPF对所依赖路径需要具备的权限。
SYS_ADMIN
:允许执行许多系统管理操作,是非常高风险的能力。NET_ADMIN
:允许进行网络管理操作,例如更改网络接口的状态、修改路由表等。NET_RAW
:允许容器直接使用原始套接字(raw socket)。SYS_RESOURCE
:允许进程修改系统资源限制。SYS_PTRACE
:允许监控其他进程。IPC_LOCK
:允许进程锁定内存页。SYSLOG
:允许对系统日志写入。重要上述示例中展示了多个可用的高风险权限,仅供测试使用。在生产环境,建议您遵循最小权限原则,只添加必要的能力。错误的配置可能会增加安全风险。
执行以下命令,进入容器。
kubectl exec -it deploy/acs-test-ebpf-demo -- bash
查看挂载的目录。
cd /sys/kernel/debug && ls -al
预期输出:
drwx------ 37 root root 0 Dec 17 08:30 . drwxr-xr-x 15 root root 0 Dec 17 08:30 .. drwxr-xr-x 2 root root 0 Dec 17 08:30 acpi drwxr-xr-x 4 root root 0 Dec 17 08:30 bdi drwxr-xr-x 4 root root 0 Dec 17 08:30 block ... drwxr-xr-x 3 root root 0 Dec 17 08:30 zram drwxr-xr-x 2 root root 0 Dec 17 08:30 zsmalloc drwxr-xr-x 2 root root 0 Dec 17 08:30 zswap
可以看到挂载正常。
进入示例应用目录。
cd /app/ebpf && ls
预期输出:
CODEOWNERS attachtype_string.go docs fuzz_test.go linker.go perf types.go CODE_OF_CONDUCT.md btf elf_reader.go go.mod linker_test.go prog.go types_string.go CONTRIBUTING.md cmd elf_reader_test.go go.sum map.go prog_test.go variable.go LICENSE collection.go elf_sections.go helpers_test.go map_test.go ringbuf variable_test.go MAINTAINERS.md collection_test.go example_sock_elf_test.go info.go marshaler_example_test.go rlimit Makefile cpu.go example_sock_extract_dist_test.go info_test.go marshalers.go syscalls.go README.md cpu_test.go examples internal marshalers_test.go syscalls_test.go asm doc.go features link netlify.toml testdata
执行以下命令,运行示例程序。
cd /app/ebpf/examples/fentry/ && go run .
预期输出:
2024/12/17 08:40:49 Comm Src addr Port -> Dest addr Port 2024/12/17 08:40:49 ilogtail 172.20.87.70 34742 -> 100.xxx.xxx.208 80 2024/12/17 08:40:53 ilogtail 172.20.87.70 37232 -> 100.xxx.xxx.112 80 2024/12/17 08:40:53 ilogtail 172.20.87.70 48676 -> 100.xxx.xxx.200 80 2024/12/17 08:40:54 ilogtail 172.20.87.70 59592 -> 100.xxx.xxx.7 80 2024/12/17 08:40:54 ilogtail 172.20.87.70 50048 -> 100.xxx.xxx.132 80 2024/12/17 08:40:54 ilogtail 172.20.87.70 51096 -> 100.xxx.xxx.210 80 2024/12/17 08:40:54 ilogtail 172.20.87.70 37808 -> 100.xxx.xxx.134 80 2024/12/17 08:40:57 ilogtail 172.20.87.70 58272 -> 100.xxx.xxx.113 80 2024/12/17 08:40:57 ilogtail 172.20.87.70 58278 -> 100.xxx.xxx.113 80 2024/12/17 08:40:57 ilogtail 172.20.87.70 58294 -> 100.xxx.xxx.113 80 2024/12/17 08:40:58 ilogtail 172.20.87.70 56356 -> 100.xxx.xxx.208 80 2024/12/17 08:41:00 ilogtail 172.20.87.70 48692 -> 100.xxx.xxx.200 80
此示例展示了最简单的eBPF程序运行的过程,您可以根据业务需要开发更复杂并贴近业务实际情况的eBPF程序。
相关信息
以下是eBPF示例中镜像的Dockerfile文件,供您参考和修改。
FROM alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest
# 1、更新包列表并安装必要的工具
RUN yum update -y && \
yum install -y wget tar gzip git util-linux net-tools
# 2、安装 Go 语言环境
ENV GO_VERSION=1.22.3
RUN wget https://golang.org/dl/go$GO_VERSION.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go$GO_VERSION.linux-amd64.tar.gz && \
rm go$GO_VERSION.linux-amd64.tar.gz
# 3、设置Go环境变量
ENV PATH=$PATH:/usr/local/go/bin
ENV GOPATH=/go
ENV PATH=$PATH:$GOPATH/bin
# 4、下载ebpf库示例代码
RUN git clone https://github.com/cilium/ebpf.git /app/ebpf/
# 5、创建工作目录
WORKDIR /app
ENTRYPOINT ["tail", "-f", "/dev/null"]