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

Dockerfile

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

DaemonSet

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.