O eBPF abre possibilidades de desenvolver ferramentas de observabilidade rodando no Kubernetes.
Pode-se começar com BCC libbpf-tools desenvolvido em C, por exemplo, iniciar o programa tcpconnlat
e processar seu stdout
com outro programa para detectar casos em que demorou muito para estabelecer uma conexão TCP.
Na prática, o comando curl <https://andrebassi.com.br
> levou 47,80 milissegundos para estabelecer uma conexão, o qual seu IP de origem seria 10.0.2.15
e o IP de destino seria 76.76.21.21
.
PID COMM IP SADDR DADDR DPORT LAT(ms)
21168 curl 4 10.0.2.15 76.76.21.21 443 47.80
FROM ubuntu:groovy as build
RUN apt-get update && \\
apt-get install -y git flex bison llvm cmake clang libclang-dev libelf-dev libcap-dev python3-setuptools && \\
apt-get autoremove -y && \\
apt-get clean && \\
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /opt/
RUN git clone <https://github.com/iovisor/bcc.git> && \\
mkdir ./bcc/build/ && \\
cd ./bcc/build/ && \\
cmake -DPYTHON_CMD=python3 .. && \\
make && \\
cd ../libbpf-tools && \\
make
FROM ubuntu:groovy
RUN apt-get update && \\
apt-get install -y libelf-dev && \\
apt-get autoremove -y && \\
apt-get clean && \\
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /opt/
COPY --from=build \\
/opt/bcc/libbpf-tools/ext4dist \\
/opt/bcc/libbpf-tools/runqlen \\
/opt/bcc/libbpf-tools/cpudist \\
/opt/bcc/libbpf-tools/softirqs \\
/opt/bcc/libbpf-tools/filelife \\
/opt/bcc/libbpf-tools/readahead \\
/opt/bcc/libbpf-tools/funclatency \\
/opt/bcc/libbpf-tools/biolatency \\
/opt/bcc/libbpf-tools/biosnoop \\
/opt/bcc/libbpf-tools/llcstat \\
/opt/bcc/libbpf-tools/biopattern \\
/opt/bcc/libbpf-tools/runqslower \\
/opt/bcc/libbpf-tools/xfsslower \\
/opt/bcc/libbpf-tools/numamove \\
/opt/bcc/libbpf-tools/hardirqs \\
/opt/bcc/libbpf-tools/bitesize \\
/opt/bcc/libbpf-tools/opensnoop \\
/opt/bcc/libbpf-tools/runqlat \\
/opt/bcc/libbpf-tools/tcpconnect \\
/opt/bcc/libbpf-tools/cpufreq \\
/opt/bcc/libbpf-tools/drsnoop \\
/opt/bcc/libbpf-tools/vfsstat \\
/opt/bcc/libbpf-tools/biostacks \\
/opt/bcc/libbpf-tools/cachestat \\
/opt/bcc/libbpf-tools/tcpconnlat \\
/opt/bcc/libbpf-tools/syscount \\
/opt/bcc/libbpf-tools/execsnoop \\
./
Crie a imagem docker:
docker build -t ttl.sh/ebpf-golang:2h .
E seu devido push:
docker push ttl.sh/ebpf-golang:2h
Um Pod
com recurso de observabilidade deve ser executada em cada node, e assim através de DaemonSet
garante que todos executem o tcpconnlat
.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: tcpconnlat-daemon
spec:
selector:
matchLabels:
app: tcpconnlat
template:
metadata:
labels:
app: tcpconnlat
spec:
containers:
- name: libbpf-tools
image: ttl.sh/ebpf-golang:2h
command:
- /opt/libbpf-tools/tcpconnlat
Infelizmente, os pods deram o status como Error, pois os containers não possuem modo privilegiado.
[1:31:15] andrebassi:~ $ kubectl get pods
NAME READY STATUS RESTARTS AGE
tcpconnlat-daemon-np6w8 0/1 Error 3 (36s ago) 64s
[1:32:17] andrebassi:~ $ kubectl logs -f tcpconnlat-daemon-np6w8
2023/01/04 04:32:11 failed to set temporary RLIMIT_MEMLOCK: operation not permitted
Por padrão, um container não tem permissão para acessar nenhum dispositivo no host, mas um container "privilegiado" tem acesso a todos os dispositivos no host.
Isso permite que o container tenha todo o mesmo acesso que os processos em execução no host.
**https://kubernetes.io/docs/concepts/security/pod-security-policy/#privileged**
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: tcpconnlat-daemon
spec:
selector:
matchLabels:
app: tcpconnlat
template:
metadata:
labels:
app: tcpconnlat
spec:
containers:
- name: libbpf-tools
image: ttl.sh/ebpf-golang:2h
command:
- /opt/libbpf-tools/tcpconnlat
securityContext:
privileged: true
Ao aplicar o manifesto acima com securityContext
com privileged
ativo com true
, teremos sucesso ao rodar o que precisamos para esse contexto.