<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Kubernetes on lo0 — Blog Técnico</title><link>https://blog.lo0.es/categories/kubernetes/</link><description>Recent content in Kubernetes on lo0 — Blog Técnico</description><generator>Hugo -- gohugo.io</generator><language>es</language><lastBuildDate>Tue, 19 May 2026 06:00:00 +0200</lastBuildDate><atom:link href="https://blog.lo0.es/categories/kubernetes/index.xml" rel="self" type="application/rss+xml"/><item><title>Hubble: observabilidad de red en eBPF, estado del arte 2026 y la nueva frontera con los agentes IA</title><link>https://blog.lo0.es/posts/hubble-observabilidad-ebpf/</link><pubDate>Tue, 19 May 2026 06:00:00 +0200</pubDate><guid>https://blog.lo0.es/posts/hubble-observabilidad-ebpf/</guid><description>&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>&lt;a href="https://github.com/cilium/hubble">Hubble&lt;/a> es &lt;strong>la observabilidad de red nativa de Cilium&lt;/strong>, construida sobre los mismos programas eBPF que Cilium usa para enforcement. No duplica datapath ni instrumenta el kernel a su manera: &lt;strong>escucha&lt;/strong> los hooks que Cilium ya tiene y produce &lt;strong>flow logs estructurados&lt;/strong> con contexto Kubernetes incluido —pod, namespace, labels, service, verdict de policy, payload L7 cuando aplica—. Es lo que pasa cuando alguien decide que &lt;code>tcpdump&lt;/code> con &lt;code>grep&lt;/code> no escala a 10 000 pods y construye un sistema distribuido propio (Hubble server por nodo + Hubble Relay como agregador + CLI + UI) con overhead &lt;strong>prácticamente cero&lt;/strong> porque la captura ya estaba ocurriendo. En 2026 está en &lt;strong>versión 1.19.3&lt;/strong> (abril 2026), con Cilium 1.19 marcando el décimo aniversario del proyecto; ha llegado el &lt;strong>tracing por IP options&lt;/strong>, el filtrado por estado de cifrado, el &lt;strong>drop event taggeado con la NetworkPolicy exacta que lo causó&lt;/strong> (atribución directa), el &lt;strong>field mask API&lt;/strong> estabilizado, y la primera oleada de &lt;strong>anomaly detection con ML aplicado a flows&lt;/strong> para predictive security en clusters IoT/5G. Y, lo más interesante para 2026: aparece una frontera nueva donde el mismo eBPF observa &lt;strong>agentes de IA&lt;/strong> —Claude Code, Gemini CLI, agentes MCP— interceptando SSL/TLS y stdio sin instrumentar el código, lo que convierte el stack Cilium + Hubble + Tetragon + &lt;strong>AgentSight&lt;/strong> en una pila completa para entender qué hace un sistema agentic dentro de un cluster.&lt;/p>
&lt;blockquote>
&lt;p>Este artículo es la &lt;strong>parte 3 de la serie sobre eBPF&lt;/strong>. Parte 1: &lt;a href="https://blog.lo0.es/posts/ebpf-cilium-tcp-ip-bypass/">eBPF de cero a Cilium: cómo el kernel aprendió a saltarse su propia pila TCP/IP&lt;/a>. Parte 2: &lt;a href="https://blog.lo0.es/posts/tetragon-runtime-security/">Tetragon: el primo de seguridad de Cilium que ve cada syscall en el kernel&lt;/a>. Aquí completamos el cuadrante de observabilidad: &lt;strong>red&lt;/strong> con Hubble, &lt;strong>proceso&lt;/strong> con Tetragon, &lt;strong>agente IA&lt;/strong> con AgentSight.&lt;/p>
&lt;/blockquote>
&lt;h2 id="la-analogía-tcpdump-que-habla-kubernetes">La analogía: tcpdump que habla Kubernetes&lt;/h2>
&lt;p>Si has administrado redes los últimos veinte años, &lt;code>tcpdump&lt;/code> y Wireshark han sido el pan nuestro de cada día. Capturan paquetes en una interfaz, los parsean, te dejan filtrar con &lt;code>tcp.port == 443 and host 10.0.0.5&lt;/code>. Funcionan, llevan funcionando desde los 90, y son lo primero que abres cuando algo huele raro.&lt;/p>
&lt;p>Ahora pega &lt;code>tcpdump&lt;/code> a un cluster Kubernetes de 10 000 pods. Los problemas saltan en orden:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Una sesión &lt;code>tcpdump&lt;/code> por nodo&lt;/strong>. Querías &amp;ldquo;ver el tráfico entre el frontend y la API&amp;rdquo;; necesitas SSH a cada nodo, tcpdump por cada NIC, sincronizar timestamps, agregar a mano.&lt;/li>
&lt;li>&lt;strong>No hay contexto K8s&lt;/strong>. Ves un paquete de &lt;code>10.244.5.7&lt;/code> a &lt;code>10.244.8.42&lt;/code>. ¿Qué pod era? ¿Qué namespace? ¿Qué label? Te toca correlar con &lt;code>kubectl get pod -A -o wide&lt;/code> cada vez.&lt;/li>
&lt;li>&lt;strong>Sin entender L7&lt;/strong>. Ves un POST a HTTPS, no puedes saber qué método y path porque está cifrado en el cable. Si hay mTLS entre pods, peor.&lt;/li>
&lt;li>&lt;strong>Coste alto&lt;/strong>: captura completa de paquetes con copia a userspace ralentiza el datapath. En tráfico denso, lo notas.&lt;/li>
&lt;/ol>
&lt;p>Hubble es &lt;strong>tcpdump rediseñado para todo eso&lt;/strong>. Reutiliza los programas eBPF que &lt;strong>ya están&lt;/strong> procesando cada paquete (Cilium los pone ahí para enforcement) y, mientras toman su decisión de allow/deny, &lt;strong>emiten un evento de flow&lt;/strong> con todo el contexto: identidad del pod origen y destino, namespace, labels, protocolo, verdict, y —si Cilium ha hecho parsing L7 vía Envoy— método HTTP, path, status code, DNS query, Kafka topic. Ese evento viaja por un ringbuffer a userspace, lo recibe el &lt;strong>Hubble server&lt;/strong> que vive dentro del agent Cilium del nodo, y lo expone vía gRPC. Un servicio aparte, &lt;strong>Hubble Relay&lt;/strong>, agrega los streams de todos los nodos y te da una única API cluster-wide. Por encima de eso: una CLI (&lt;code>hubble&lt;/code>) y una UI web con grafo de servicios en tiempo real.&lt;/p>
&lt;p>Cero copia adicional. Cero parsing duplicado. Y el resultado lo entiende cualquiera que sepa qué es un Pod.&lt;/p>
&lt;h2 id="arquitectura-cuatro-piezas-que-se-ven-desde-fuera">Arquitectura: cuatro piezas que se ven desde fuera&lt;/h2>
&lt;p>Hubble se compone de cuatro componentes lógicos, todos opcionales según lo que quieras hacer:&lt;/p>
&lt;h3 id="1-hubble-server-embedded-en-cada-agent-cilium">1. Hubble Server (embedded en cada agent Cilium)&lt;/h3>
&lt;p>Vive &lt;strong>dentro del proceso del agent Cilium&lt;/strong> (no es un binario aparte). Cada nodo expone localmente un endpoint gRPC en el socket Unix &lt;code>/var/run/cilium/hubble.sock&lt;/code>. El server escucha los eventos que los programas eBPF emiten al ringbuffer, los enriquece con metadata Kubernetes (que el agent ya tiene en memoria), y los pone disponibles para consumidores.&lt;/p>
&lt;p>Activación: &lt;code>--set hubble.enabled=true&lt;/code> en el chart Helm de Cilium. Por defecto, el server &lt;strong>solo es accesible localmente&lt;/strong>; si quieres consumirlo desde otro nodo, hace falta exponerlo (lo que hace Hubble Relay).&lt;/p>
&lt;h3 id="2-hubble-relay-agregador">2. Hubble Relay (agregador)&lt;/h3>
&lt;p>Es un Deployment aparte (típicamente 1 réplica, escalable) que &lt;strong>se conecta a todos los Hubble servers del cluster&lt;/strong> y &lt;strong>agrega sus streams en una única API&lt;/strong>. Cuando tu CLI o UI pide &amp;ldquo;los últimos 1000 flows del cluster&amp;rdquo;, la Relay los recoge en paralelo de todos los nodos y devuelve la unión.&lt;/p>
&lt;p>Activación: &lt;code>--set hubble.relay.enabled=true&lt;/code>. Sin la Relay, solo ves el tráfico del nodo donde estás conectado, lo que es útil para debug local pero no para visión cluster-wide.&lt;/p>
&lt;h3 id="3-hubble-cli-hubble">3. Hubble CLI (&lt;code>hubble&lt;/code>)&lt;/h3>
&lt;p>Un binario en Go que habla gRPC con la Relay (o con un Hubble server local). Soporta dos modos principales:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>hubble observe&lt;/code>&lt;/strong>: stream de flows en tiempo real, con filtros muy expresivos (por namespace, pod, port, verdict, protocolo, label).&lt;/li>
&lt;li>&lt;strong>&lt;code>hubble status&lt;/code>&lt;/strong>: estado del cluster Hubble (cuántos nodos conectados, lag, flow rate).&lt;/li>
&lt;/ul>
&lt;p>Y el equivalente a &lt;code>tcpdump&lt;/code>&amp;rsquo;s pcap dump: &lt;code>hubble observe --output jsonpb &amp;gt; flows.json&lt;/code> para procesar a posteriori con &lt;code>jq&lt;/code> u otras herramientas.&lt;/p>
&lt;h3 id="4-hubble-ui">4. Hubble UI&lt;/h3>
&lt;p>Frontend web que se conecta a Hubble Relay y muestra:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Grafo de servicios&lt;/strong> en tiempo real (qué Pod habla con qué Service, qué protocolos usa, qué verdict).&lt;/li>
&lt;li>&lt;strong>Lista de flows&lt;/strong> filtrable.&lt;/li>
&lt;li>&lt;strong>Detalles L7&lt;/strong> cuando los hay (HTTP method/path/status, DNS query/response).&lt;/li>
&lt;/ul>
&lt;p>Activación: &lt;code>--set hubble.ui.enabled=true&lt;/code>. Útil para presentaciones a equipos no-CLI; no sustituye a la CLI para debug serio.&lt;/p>
&lt;div class="diagram" style="max-width:720px;margin:1.5rem auto;">
&lt;svg viewBox="0 0 720 290" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Arquitectura de Hubble">
&lt;style>.title{font:600 13px sans-serif;fill:#222}.lbl{font:600 12px sans-serif;fill:#222}.sm{font:11px sans-serif;fill:#555}.box{stroke:#444;stroke-width:1.4}.k{fill:#ffe9d6}.s{fill:#d6eaff}.r{fill:#d9f5d6}.c{fill:#e9d6f5}.arr{stroke:#666;stroke-width:1.4;fill:none;marker-end:url(#hh)}&lt;/style>
&lt;defs>&lt;marker id="hh" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">&lt;path d="M0,0 L10,5 L0,10 z" fill="#666"/>&lt;/marker>&lt;/defs>
&lt;text x="360" y="18" text-anchor="middle" class="title">Arquitectura Hubble: 4 piezas, eBPF como única fuente de datos&lt;/text>
&lt;rect x="30" y="40" width="200" height="50" rx="6" class="box k"/>
&lt;text x="130" y="60" text-anchor="middle" class="lbl">eBPF (kernel)&lt;/text>
&lt;text x="130" y="78" text-anchor="middle" class="sm">programs de Cilium&lt;/text>
&lt;rect x="30" y="115" width="200" height="50" rx="6" class="box s"/>
&lt;text x="130" y="135" text-anchor="middle" class="lbl">Hubble Server (nodo)&lt;/text>
&lt;text x="130" y="153" text-anchor="middle" class="sm">grpc local, dentro del agent&lt;/text>
&lt;rect x="270" y="115" width="180" height="50" rx="6" class="box s"/>
&lt;text x="360" y="135" text-anchor="middle" class="lbl">Hubble Server (nodo N)&lt;/text>
&lt;text x="360" y="153" text-anchor="middle" class="sm">uno por nodo&lt;/text>
&lt;rect x="490" y="115" width="200" height="50" rx="6" class="box s"/>
&lt;text x="590" y="135" text-anchor="middle" class="lbl">Hubble Server (nodo …)&lt;/text>
&lt;text x="590" y="153" text-anchor="middle" class="sm">N agents = N servers&lt;/text>
&lt;rect x="220" y="190" width="280" height="50" rx="6" class="box r"/>
&lt;text x="360" y="210" text-anchor="middle" class="lbl">Hubble Relay (Deployment)&lt;/text>
&lt;text x="360" y="228" text-anchor="middle" class="sm">agrega streams gRPC de todos los nodos&lt;/text>
&lt;rect x="80" y="245" width="160" height="35" rx="6" class="box c"/>
&lt;text x="160" y="266" text-anchor="middle" class="lbl">Hubble CLI&lt;/text>
&lt;rect x="290" y="245" width="160" height="35" rx="6" class="box c"/>
&lt;text x="370" y="266" text-anchor="middle" class="lbl">Hubble UI&lt;/text>
&lt;rect x="500" y="245" width="180" height="35" rx="6" class="box c"/>
&lt;text x="590" y="266" text-anchor="middle" class="lbl">Prometheus / OTLP&lt;/text>
&lt;path class="arr" d="M130,90 L130,115"/>
&lt;path class="arr" d="M130,165 L290,190"/>
&lt;path class="arr" d="M360,165 L360,190"/>
&lt;path class="arr" d="M590,165 L430,190"/>
&lt;path class="arr" d="M340,240 L200,245"/>
&lt;path class="arr" d="M360,240 L370,245"/>
&lt;path class="arr" d="M380,240 L560,245"/>
&lt;/svg>
&lt;/div>
&lt;h2 id="qué-se-ve-el-flow-log-de-hubble-por-dentro">Qué se ve: el flow log de Hubble por dentro&lt;/h2>
&lt;p>Un flow de Hubble en formato JSON tiene aproximadamente esta forma (simplificado):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2026-05-19T03:12:45.182Z&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;verdict&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FORWARDED&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;source&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ID&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5482&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;identity&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">24871&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;namespace&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;prod-api&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;labels&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;app=checkout&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;team=payments&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;pod_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;checkout-7c9f-x8j2&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;workloads&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;checkout&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;kind&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Deployment&amp;#34;&lt;/span>&lt;span class="p">}]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;destination&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ID&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">12041&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;identity&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">18356&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;namespace&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;prod-db&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;labels&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;app=postgres&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;tier=primary&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;pod_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;postgres-0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;L3_L4&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;l4&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;TCP&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;source_port&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">41982&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;destination_port&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5432&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;flags&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;SYN&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;node_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;rke2-worker-03&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Summary&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TCP Flags: SYN&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Cuando hay parsing L7 activo (vía Envoy embebido o el parser ligero de Hubble), el mismo flujo añade:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;l7&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;REQUEST&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;http&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;code&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;method&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;GET&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/api/v1/cart/items&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;protocol&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HTTP/1.1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;headers&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="nt">&amp;#34;key&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user-agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;value&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;checkout/1.4.2&amp;#34;&lt;/span>&lt;span class="p">}]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Los protocolos soportados nativamente para parsing L7:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>HTTP/1.1 y HTTP/2&lt;/strong> (incluyendo gRPC sobre HTTP/2).&lt;/li>
&lt;li>&lt;strong>DNS&lt;/strong> (queries y responses, con domains, tipos, response codes).&lt;/li>
&lt;li>&lt;strong>Kafka&lt;/strong> (topics, API keys).&lt;/li>
&lt;li>&lt;strong>TLS handshake&lt;/strong> (SNI, no el payload cifrado por defecto).&lt;/li>
&lt;li>&lt;strong>MySQL, Cassandra&lt;/strong> (con módulos opcionales).&lt;/li>
&lt;/ul>
&lt;p>Para HTTP y gRPC, Cilium puede activar el proxy Envoy embebido para los flujos que quieras inspeccionar (no todos; selectivo via &lt;code>CiliumNetworkPolicy&lt;/code> con reglas L7). Sin Envoy hay parsing ligero pero menos detallado.&lt;/p>
&lt;h2 id="verdict-y-atribución-de-drops">Verdict y atribución de drops&lt;/h2>
&lt;p>Cada flow tiene un &lt;code>verdict&lt;/code>: &lt;code>FORWARDED&lt;/code>, &lt;code>DROPPED&lt;/code>, &lt;code>ERROR&lt;/code>, &lt;code>AUDIT&lt;/code>, &lt;code>REDIRECTED&lt;/code>, &lt;code>TRACED&lt;/code>, &lt;code>TRANSLATED&lt;/code>. Para el caso &lt;code>DROPPED&lt;/code>, Hubble incluye una &lt;strong>razón estructurada&lt;/strong> (&lt;code>drop_reason&lt;/code>) y, desde Cilium 1.19, &lt;strong>la NetworkPolicy exacta&lt;/strong> que lo causó.&lt;/p>
&lt;p>Esto último cambia la operativa. Antes, cuando un pod no podía hablar con otro, el flujo de debug era:&lt;/p>
&lt;ol>
&lt;li>Ver el flow dropeado en Hubble.&lt;/li>
&lt;li>Mirar todas las CiliumNetworkPolicy del namespace.&lt;/li>
&lt;li>Razonar a mano cuál de ellas, con cuáles labels, lo está bloqueando.&lt;/li>
&lt;/ol>
&lt;p>Con la atribución de Cilium 1.19, el campo &lt;code>policy_match_info&lt;/code> te dice directamente &amp;ldquo;lo dropeó la policy &lt;code>frontend-egress&lt;/code>, regla 3&amp;rdquo;. Pasas de &amp;ldquo;Sherlock Holmes durante 20 minutos&amp;rdquo; a &amp;ldquo;kubectl get -o yaml de esa policy concreta&amp;rdquo;.&lt;/p>
&lt;h2 id="métricas-prometheus-y-dashboards-grafana">Métricas Prometheus y dashboards Grafana&lt;/h2>
&lt;p>Hubble también expone &lt;strong>métricas agregadas&lt;/strong> en formato Prometheus, separadas del stream gRPC de flows. Activación: &lt;code>--set hubble.metrics.enabled=true&lt;/code> (Helm) y enumeración del set que quieres exportar.&lt;/p>
&lt;p>Los grupos de métricas habituales:&lt;/p>
&lt;ul>
&lt;li>&lt;code>flow&lt;/code>: total flows por verdict, source/dest, protocolo.&lt;/li>
&lt;li>&lt;code>http&lt;/code>: requests por método, código de respuesta, latencia (histograma).&lt;/li>
&lt;li>&lt;code>dns&lt;/code>: queries, response codes, dominios top-N.&lt;/li>
&lt;li>&lt;code>tcp&lt;/code>: handshakes, retransmisiones, ventana congestion.&lt;/li>
&lt;li>&lt;code>drop&lt;/code>: drops por razón, con NetworkPolicy attribution.&lt;/li>
&lt;li>&lt;code>port-distribution&lt;/code>: histograma de ports activos.&lt;/li>
&lt;li>&lt;code>policy&lt;/code>: hits por policy y verdict.&lt;/li>
&lt;/ul>
&lt;p>Estas métricas tienen labels K8s ricos (&lt;code>source_workload&lt;/code>, &lt;code>destination_workload&lt;/code>, &lt;code>namespace&lt;/code>, etc.) que las hacen pivotables en Grafana. Hay &lt;a href="https://grafana.com/grafana/dashboards/?search=hubble">dashboards prebuilt en Grafana Labs&lt;/a> que cubren los casos comunes; importar uno y tener visión inmediata cuesta cinco minutos.&lt;/p>
&lt;p>Coste: las métricas con muchos labels K8s pueden &lt;strong>explotar la cardinalidad&lt;/strong> en Prometheus. Para clusters grandes (&amp;gt;1 000 pods), conviene revisar qué set exportas y usar &lt;strong>drop rules&lt;/strong> en Prometheus para limitar.&lt;/p>
&lt;h2 id="despliegue-helm-en-una-pantalla">Despliegue: Helm en una pantalla&lt;/h2>
&lt;p>Instalación canónica de Cilium con Hubble completo:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># values.yaml&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">hubble&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">metrics&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">dns:query;ignoreAAAA&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">drop&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">tcp&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">flow&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">port-distribution&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">icmp&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">httpV2:exemplars=true;labelsContext=source_ip,source_namespace,source_workload,destination_ip,destination_namespace,destination_workload,traffic_direction&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">serviceMonitor&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># auto-discover por kube-prometheus-stack&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">relay&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">rollOutPods&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ui&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">rollOutPods&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ingress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">className&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">hosts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">hubble.example.local&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Y la instalación:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">helm upgrade --install cilium cilium/cilium -n kube-system -f values.yaml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Tras la instalación, valida con &lt;code>cilium status&lt;/code> (CLI de Cilium) que la sección Hubble muestra OK, y prueba el primer flow con:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cilium hubble observe --namespace prod-api --pod checkout-7c9f-x8j2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="estado-del-arte-en-2026">Estado del arte en 2026&lt;/h2>
&lt;p>&lt;a href="https://www.infoq.com/news/2026/02/cilium-119/">Cilium 1.19 se publicó en febrero de 2026&lt;/a> marcando el décimo aniversario del proyecto. Hubble alcanzó la versión 1.19.3 el 22 de abril de 2026. Las novedades relevantes:&lt;/p>
&lt;h3 id="atribución-directa-de-drops-a-networkpolicy">Atribución directa de drops a NetworkPolicy&lt;/h3>
&lt;p>Ya cubierta arriba; es probablemente el cambio operacional más valioso del release. Cualquier flow dropeado lleva el nombre, namespace y regla específica de la policy responsable. Aplicable también vía métricas Prometheus, lo que permite alertas tipo &amp;ldquo;policy X está dropping &amp;gt;N peticiones/segundo&amp;rdquo;.&lt;/p>
&lt;h3 id="tracing-con-ip-options">Tracing con IP options&lt;/h3>
&lt;p>Hubble puede ahora &lt;strong>trazar paquetes individuales con IP options&lt;/strong> activado. Es un mecanismo similar al traceroute pero a nivel L3: pones una marca en el paquete y Cilium la reporta cada vez que el paquete atraviesa un nodo o una decisión de eBPF. Útil para debug de paths multi-cluster, fabric mesh, o NetworkPolicy que se aplican en distintas capas.&lt;/p>
&lt;h3 id="filtrado-por-estado-de-cifrado">Filtrado por estado de cifrado&lt;/h3>
&lt;p>Nuevo flag en CLI: &lt;code>hubble observe --encryption-status=encrypted&lt;/code> (o &lt;code>unencrypted&lt;/code>). Útil para validar despliegues con WireGuard o IPsec activado pod-a-pod: confirmas que el tráfico que &lt;strong>debería&lt;/strong> estar cifrado lo está, y detectas regresiones rápidamente.&lt;/p>
&lt;h3 id="hubble-field-mask-api-estabilizado">Hubble field mask API estabilizado&lt;/h3>
&lt;p>El &lt;code>field_mask&lt;/code> permite pedir solo las partes del flow que te interesan, reduciendo enormemente el ancho de banda y el procesamiento cuando solo necesitas, por ejemplo, source/dest y verdict. Antes era experimental, ahora está estable y es &lt;strong>default-on&lt;/strong> en la CLI.&lt;/p>
&lt;h3 id="ai-driven-anomaly-detection-predictive-security">AI-driven anomaly detection (predictive security)&lt;/h3>
&lt;p>Esta es la incorporación más comentada de 2026. Cilium 1.19 añade hooks para que un consumer externo —típicamente un sistema ML— procese los flows en streaming y detecte anomalías estadísticas: pods que de pronto hablan con destinos nuevos, picos de latencia en una API, secuencias raras de DNS. La parte de &lt;strong>detección&lt;/strong> ocurre fuera del agent Cilium (no se quiere ML pesado en el datapath), pero Cilium expone los flows con las features pre-calculadas que el modelo necesita. Los casos de uso publicados se enfocan en &lt;strong>IoT y 5G&lt;/strong> donde el tráfico es alto en volumen y bajo en variedad, condiciones ideales para anomaly detection.&lt;/p>
&lt;h3 id="escala-a-10-000-pods">Escala a 10 000+ pods&lt;/h3>
&lt;p>Cilium 1.19 ha hecho trabajo serio en escalabilidad: Hubble Relay puede ahora agregar streams de cientos de nodos sin saturar; el field_mask por defecto reduce el ancho de banda inter-nodo; y los flows pueden samplearse en alta carga si tu uso es análisis estadístico (no debug forense).&lt;/p>
&lt;h3 id="cilium-120-en-desarrollo">Cilium 1.20 en desarrollo&lt;/h3>
&lt;p>&lt;a href="https://docs.cilium.io/en/latest/operations/upgrade/">Cilium 1.20&lt;/a> está en branch de desarrollo. Lo más relevante para Hubble:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Unificación de &lt;code>preferIpv6&lt;/code>&lt;/strong>: el flag &lt;code>hubble.preferIpv6&lt;/code> se deprecó en favor del global &lt;code>preferIpv6&lt;/code> aplicable a todos los componentes Cilium.&lt;/li>
&lt;li>&lt;strong>&lt;code>tetragon-python&lt;/code> SDK&lt;/strong>: aunque es de Tetragon, no de Hubble, marca tendencia: políticas eBPF escritas en Python en lugar de YAML. Probablemente Hubble seguirá camino similar.&lt;/li>
&lt;/ul>
&lt;h2 id="la-nueva-frontera-ebpf-y-los-agentes-de-ia">La nueva frontera: eBPF y los agentes de IA&lt;/h2>
&lt;p>Hasta aquí el contenido clásico de Hubble. Pero hay un giro 2026 que merece la pena cubrir porque cierra el círculo con la otra serie de este blog.&lt;/p>
&lt;p>Cuando un cluster Kubernetes empieza a ejecutar &lt;strong>agentes de IA&lt;/strong> —Claude Code, Gemini CLI, agentes basados en LangGraph que llaman APIs y MCP servers—, el problema de observabilidad cambia de forma. Ya no basta con saber &amp;ldquo;qué pod habló con qué pod&amp;rdquo; (eso es Hubble) ni &amp;ldquo;qué proceso ejecutó qué&amp;rdquo; (eso es Tetragon). Necesitas saber:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>A qué APIs externas está llamando el agente&lt;/strong> y con qué prompts.&lt;/li>
&lt;li>&lt;strong>Qué herramientas MCP está invocando&lt;/strong>, con qué argumentos.&lt;/li>
&lt;li>&lt;strong>Cuántos tokens consume&lt;/strong>, qué modelo elige, cuánto cuesta.&lt;/li>
&lt;li>&lt;strong>Si el agente se desvía&lt;/strong> del comportamiento esperado (out-of-policy queries, intentos de jailbreak, leakage de secretos).&lt;/li>
&lt;/ul>
&lt;p>Las soluciones tradicionales —instrumentar el código del agente con OpenTelemetry, parsear logs estructurados— no funcionan bien cuando el agente es un binario de terceros (Claude Code de Anthropic, Gemini CLI de Google) o cuando los MCP servers viven en otros lenguajes con stdio como transport.&lt;/p>
&lt;h3 id="agentsight-zero-instrumentation-para-agentes-llm">AgentSight: zero-instrumentation para agentes LLM&lt;/h3>
&lt;p>&lt;a href="https://github.com/eunomia-bpf/agentsight">&lt;strong>AgentSight&lt;/strong>&lt;/a> (proyecto del grupo &lt;code>eunomia-bpf&lt;/code>, mismo ecosistema de varios runtimes eBPF de alto perfil) ataca este problema con la misma filosofía que Hubble: &lt;strong>no instrumentes; escucha&lt;/strong>. Pone hooks eBPF en dos puntos críticos:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>uprobes en bibliotecas SSL/TLS&lt;/strong> (&lt;code>libssl&lt;/code>, &lt;code>boringssl&lt;/code>, &lt;code>rustls&lt;/code>). Captura el plaintext &lt;strong>antes&lt;/strong> del cifrado en send y &lt;strong>después&lt;/strong> del descifrado en recv. Para una llamada HTTP a &lt;code>https://api.anthropic.com/v1/messages&lt;/code>, AgentSight ve el JSON completo del prompt y la respuesta &lt;strong>sin descifrar nada en transit&lt;/strong>, simplemente porque ha llegado al nivel del syscall antes de que la TLS layer haga su trabajo.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>&lt;code>stdiocap&lt;/code> BPF&lt;/strong>: captura &lt;code>read&lt;/code>, &lt;code>write&lt;/code>, &lt;code>dup&lt;/code> sobre los file descriptors de stdin/stdout/stderr de un proceso. Esto es lo que permite observar &lt;strong>MCP servers que hablan stdio&lt;/strong> con su cliente —el patrón habitual de los servers MCP locales—. Capturas el JSON-RPC que va y viene sin que ni el cliente ni el server lo sepan.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Sobrecarga reportada: &lt;strong>&amp;lt;3% CPU&lt;/strong>, comparable a Hubble en su régimen.&lt;/p>
&lt;h3 id="cómo-encaja-con-hubble-y-tetragon">Cómo encaja con Hubble y Tetragon&lt;/h3>
&lt;p>Los tres se complementan limpiamente:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Hubble&lt;/strong> te dice: &amp;ldquo;el pod del agente abrió conexión TCP a &lt;code>api.anthropic.com:443&lt;/code> con verdict ALLOW&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>Tetragon&lt;/strong> te dice: &amp;ldquo;el proceso &lt;code>claude-code&lt;/code> con PID 1843 hizo &lt;code>connect()&lt;/code> a esa IP&amp;rdquo; (más el binario, los argumentos, el namespace de pod).&lt;/li>
&lt;li>&lt;strong>AgentSight&lt;/strong> te dice: &amp;ldquo;el contenido HTTPS de esa conexión era un prompt &lt;code>messages=[{role:'user', content:'analyze this repo and modify the firewall config'}]&lt;/code> y la respuesta incluyó una tool call a &lt;code>read_file&lt;/code> con argument &lt;code>/etc/passwd&lt;/code>&amp;rdquo;.&lt;/li>
&lt;/ul>
&lt;p>Es la diferencia entre &lt;strong>flujo, proceso y semántica&lt;/strong>. Para un equipo de seguridad que quiera vigilar agentes de IA en producción, los tres son necesarios. Para alguien que quiera entender el coste, los tres son útiles (Hubble para latencia de red, Tetragon para uso de recursos, AgentSight para tokens y modelo elegido).&lt;/p>
&lt;h3 id="casos-de-uso-emergentes">Casos de uso emergentes&lt;/h3>
&lt;p>Los patrones que se están consolidando en 2026:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Audit trail de agentes&lt;/strong>: registrar cada llamada a LLM y cada tool call para compliance (sobre todo en sectores regulados).&lt;/li>
&lt;li>&lt;strong>Detección de jailbreak y prompt injection&lt;/strong>: aplicar reglas sobre los prompts capturados por AgentSight (similar a las TracingPolicy de Tetragon, pero sobre contenido semántico).&lt;/li>
&lt;li>&lt;strong>Cost accountability&lt;/strong>: ver qué team/agente consume qué tokens, sin instrumentar.&lt;/li>
&lt;li>&lt;strong>Replay y debug&lt;/strong>: reproducir el reasoning de un agente en producción sin pedirle que vuelva a ejecutar (que es no-determinístico).&lt;/li>
&lt;/ul>
&lt;p>Es un campo joven —AgentSight tiene meses, no años— pero el patrón &amp;ldquo;eBPF como observabilidad zero-instrumentation&amp;rdquo; está clarísimamente extendiéndose más allá de red y proceso. El próximo año va a ver consolidación y, probablemente, integración nativa con Hubble.&lt;/p>
&lt;h2 id="casos-de-uso-habituales-de-hubble">Casos de uso habituales de Hubble&lt;/h2>
&lt;p>Volviendo a Hubble propiamente, los casos en los que cualquier organización lo despliega:&lt;/p>
&lt;h3 id="1-debug-de-networkpolicy">1. Debug de NetworkPolicy&lt;/h3>
&lt;p>El uso clásico: &amp;ldquo;este pod no llega a este Service&amp;rdquo;. Sin Hubble, tocaba SSH, tcpdump, comparar reglas. Con Hubble:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">hubble observe --from-pod prod-api/checkout --to-pod prod-db/postgres --verdict DROPPED
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Si hay drops, ves la policy responsable (Cilium 1.19+). Si no hay drops, el problema no es policy: es DNS, routing o el target service.&lt;/p>
&lt;h3 id="2-audit-de-comunicación-inter-namespace">2. Audit de comunicación inter-namespace&lt;/h3>
&lt;p>Para compliance: validar que namespaces aislados no están comunicándose contra lo declarado.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">hubble observe --from-namespace prod-payments --to-namespace &lt;span class="s1">&amp;#39;NOT prod-db&amp;#39;&lt;/span> --output json
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="3-detección-de-exfiltración">3. Detección de exfiltración&lt;/h3>
&lt;p>Tráfico saliente a destinos públicos sospechosos. Hubble los detecta por IP/SNI, no por payload (que está cifrado):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">hubble observe --to-fqdn &lt;span class="s1">&amp;#39;NOT *.example.com&amp;#39;&lt;/span> --to-fqdn &lt;span class="s1">&amp;#39;NOT *.internal&amp;#39;&lt;/span> --protocol tcp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Combinado con métricas Prometheus y alertas en Grafana, esto da un radar de exfiltración a coste cero.&lt;/p>
&lt;h3 id="4-slo-de-servicio-en-tiempo-real">4. SLO de servicio en tiempo real&lt;/h3>
&lt;p>Métricas &lt;code>hubble:http:response_time_seconds&lt;/code> con labels &lt;code>source_workload&lt;/code>, &lt;code>destination_workload&lt;/code>, &lt;code>method&lt;/code>, &lt;code>status_code&lt;/code> permiten dashboards SLO sin necesidad de instrumentar las apps. El SRE ve la latencia p95 de &lt;code>checkout → catalog&lt;/code> directamente.&lt;/p>
&lt;h3 id="5-performance-debugging">5. Performance debugging&lt;/h3>
&lt;p>&lt;code>hubble:tcp:retransmissions_total&lt;/code> y &lt;code>hubble:tcp:flags_total{flag=&amp;quot;RST&amp;quot;}&lt;/code> son señales tempranas de problemas de red. Una subida correlada con regresión de latencia te apunta a algo en infraestructura (NIC, switch, MTU) antes de bajar a investigar la app.&lt;/p>
&lt;h3 id="6-forensics-post-incidente">6. Forensics post-incidente&lt;/h3>
&lt;p>Configurar Hubble para exportar flows a almacenamiento persistente (vía OTLP a Tempo/Loki, o &lt;code>hubble observe --output jsonpb&lt;/code> a S3) te da capacidad forense: si en T+30 días detectas que algo iba mal en T, puedes reconstruir el tráfico.&lt;/p>
&lt;h2 id="hubble-y-el-resto-del-stack-de-observabilidad">Hubble y el resto del stack de observabilidad&lt;/h2>
&lt;p>Hubble no reemplaza Prometheus, Loki, Tempo ni Jaeger; los complementa:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Prometheus&lt;/strong>: recibe las métricas agregadas de Hubble. Hubble exporta endpoint Prometheus nativo.&lt;/li>
&lt;li>&lt;strong>Loki&lt;/strong>: recibe los flow logs estructurados si los exportas como logs. Hubble no tiene exporter nativo a Loki, pero un Fluent Bit con plugin OTLP o uno custom hace el puente fácilmente.&lt;/li>
&lt;li>&lt;strong>Tempo / Jaeger&lt;/strong>: el Cilium Operator tiene exportador OTLP de flows en formato traces (cada flujo HTTP/gRPC es un span). Integra con Tempo o cualquier otro tracing backend OTLP.&lt;/li>
&lt;li>&lt;strong>Grafana&lt;/strong>: ya hay dashboards públicos de Hubble. Combinados con Prometheus, Loki y Tempo, te dan un panel unificado: métricas, logs, traces, todo correlado por labels K8s.&lt;/li>
&lt;/ul>
&lt;p>La pila full-stack que se ve en producción 2026 (descrita en &lt;a href="https://dev.to/x4nent/building-a-production-ebpf-observability-security-stack-for-kubernetes-in-2026-5051">Building a Production eBPF Observability &amp;amp; Security Stack for Kubernetes in 2026&lt;/a>):&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Datos&lt;/strong>: Cilium + Hubble (red), Tetragon (proceso), AgentSight (agente IA).&lt;/li>
&lt;li>&lt;strong>Pipeline&lt;/strong>: OTLP Collector como router único.&lt;/li>
&lt;li>&lt;strong>Almacenamiento&lt;/strong>: Prometheus (métricas), Loki (logs), Tempo (traces).&lt;/li>
&lt;li>&lt;strong>UI&lt;/strong>: Grafana con dashboards específicos por dominio.&lt;/li>
&lt;li>&lt;strong>Alerting&lt;/strong>: AlertManager con reglas sobre las métricas Hubble + Tetragon.&lt;/li>
&lt;/ul>
&lt;h2 id="comparativa-con-alternativas">Comparativa con alternativas&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Sistema&lt;/th>
&lt;th>Capa&lt;/th>
&lt;th>Foco&lt;/th>
&lt;th>Modelo&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Hubble&lt;/strong>&lt;/td>
&lt;td>L3-L7 red&lt;/td>
&lt;td>Cluster K8s con Cilium&lt;/td>
&lt;td>eBPF, pull metrics, push flows gRPC&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>GKE Dataplane v2 obs&lt;/strong>&lt;/td>
&lt;td>L3-L7 red&lt;/td>
&lt;td>GKE managed&lt;/td>
&lt;td>eBPF (Cilium-based, gestionado)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Tigera Calico Whisker&lt;/strong>&lt;/td>
&lt;td>L3-L7 red&lt;/td>
&lt;td>Cluster con Calico&lt;/td>
&lt;td>eBPF + pcap, UI propia&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Tetragon&lt;/strong>&lt;/td>
&lt;td>Proceso/syscall&lt;/td>
&lt;td>Cluster K8s&lt;/td>
&lt;td>eBPF, push events gRPC&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Falco&lt;/strong>&lt;/td>
&lt;td>Proceso/syscall&lt;/td>
&lt;td>Cluster K8s&lt;/td>
&lt;td>eBPF en userspace o módulo kernel&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>AgentSight&lt;/strong>&lt;/td>
&lt;td>Agente LLM&lt;/td>
&lt;td>Sistemas agentic&lt;/td>
&lt;td>eBPF (SSL uprobes + stdio)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Beyla&lt;/strong> (Grafana)&lt;/td>
&lt;td>Aplicación&lt;/td>
&lt;td>App L7 + tracing&lt;/td>
&lt;td>eBPF (uprobes en libs)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Pixie&lt;/strong>&lt;/td>
&lt;td>App + sistema&lt;/td>
&lt;td>Visibilidad cluster amplia&lt;/td>
&lt;td>eBPF + script PXL&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Parca&lt;/strong>&lt;/td>
&lt;td>Profiling CPU/mem&lt;/td>
&lt;td>Performance&lt;/td>
&lt;td>eBPF profile sampling&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Si tu CNI es Cilium, &lt;strong>Hubble es el punto de entrada natural&lt;/strong> y no compite con los demás: complementa. Para clusters Calico, Whisker es el equivalente. Para profiling, Parca. Para agentes IA, AgentSight. La era del &amp;ldquo;una herramienta para todo&amp;rdquo; está pasando: la pila moderna combina varias piezas especializadas, todas basadas en eBPF, expuestas vía OTLP.&lt;/p>
&lt;h2 id="trampas-operativas">Trampas operativas&lt;/h2>
&lt;h3 id="cardinalidad-en-prometheus">Cardinalidad en Prometheus&lt;/h3>
&lt;p>Las métricas Hubble con todos los labels K8s pueden explotar Prometheus. &lt;strong>Mide la cardinalidad antes de exportar todo&lt;/strong>. Las métricas más prolíficas son &lt;code>flow&lt;/code> y &lt;code>httpV2&lt;/code>; empieza por &lt;code>drop&lt;/code> y &lt;code>port-distribution&lt;/code> y añade el resto incrementalmente.&lt;/p>
&lt;h3 id="l7-visibility-cuesta-cpu">L7 visibility cuesta CPU&lt;/h3>
&lt;p>Activar parsing L7 vía Envoy embebido añade carga al agent (no al datapath base, pero sí al envoy proxy del nodo). Para tráfico HTTP intenso, mide. Para flujos donde solo necesitas L4, deja Envoy desactivado.&lt;/p>
&lt;h3 id="hubble-relay-sin-ha">Hubble Relay sin HA&lt;/h3>
&lt;p>Una sola réplica de Relay es un single point of failure para CLI y UI (no para el agent local, que sigue funcionando). Para producción, deploy con &lt;code>replicas: 2+&lt;/code> y &lt;code>topologySpreadConstraints&lt;/code> para que no caigan ambas.&lt;/p>
&lt;h3 id="encryption-status-reporting-depende-de-cilium-config">Encryption status reporting depende de Cilium config&lt;/h3>
&lt;p>El nuevo filtro &lt;code>--encryption-status&lt;/code> solo da datos reales si Cilium tiene encryption activado (WireGuard o IPsec). Sin esto, todo es &lt;code>unencrypted&lt;/code> y el filtro no aporta.&lt;/p>
&lt;h3 id="ui-expuesta-sin-auth">UI expuesta sin auth&lt;/h3>
&lt;p>Hubble UI no tiene auth nativa. Si la expones por Ingress, &lt;strong>delante tiene que haber autenticación&lt;/strong>: OIDC vía oauth2-proxy, mTLS, IP allowlist. No es opcional.&lt;/p>
&lt;h3 id="storage-no-escalado">Storage no escalado&lt;/h3>
&lt;p>Si guardas flows durante días para forensics, el volumen es serio. Para un cluster de 100 pods activos, fácilmente 1-10 GB/día de flow logs. Plantea el ciclo de vida (compactación, retención, cold storage) antes de habilitarlo.&lt;/p>
&lt;h2 id="lo-que-no-hemos-cubierto">Lo que no hemos cubierto&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Mesh / multi-cluster Hubble&lt;/strong>: agregar flows de varios clusters Cilium en una sola Relay. Caso de uso: visión cross-cluster, debug de service mesh distribuido.&lt;/li>
&lt;li>&lt;strong>&lt;code>hubble export&lt;/code>&lt;/strong>: persistencia local en disco del agent para forensics con baja retención.&lt;/li>
&lt;li>&lt;strong>Anomaly detection con modelos propios&lt;/strong>: cómo conectar el stream gRPC a un consumer ML personalizado.&lt;/li>
&lt;li>&lt;strong>AgentSight en profundidad&lt;/strong>: el proyecto merece su propio artículo. Próxima entrega.&lt;/li>
&lt;li>&lt;strong>eBPF para profiling de LLM serving&lt;/strong>: cómo medir TTFT, TPOT y throughput de vLLM sin instrumentar, usando uprobes en libcudart.&lt;/li>
&lt;/ul>
&lt;h2 id="referencias">Referencias&lt;/h2>
&lt;p>Hubble y Cilium:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/cilium/hubble">Hubble GitHub&lt;/a> — repo principal.&lt;/li>
&lt;li>&lt;a href="https://docs.cilium.io/en/stable/observability/hubble/">Hubble — Network Observability (Cilium docs)&lt;/a> — referencia oficial.&lt;/li>
&lt;li>&lt;a href="https://www.infoq.com/news/2026/02/cilium-119/">Cilium 1.19 release notes (InfoQ, feb 2026)&lt;/a> — décimo aniversario y novedades 1.19.&lt;/li>
&lt;li>&lt;a href="https://github.com/cilium/cilium/releases">Cilium releases&lt;/a> — todos los releases.&lt;/li>
&lt;li>&lt;a href="https://grafana.com/grafana/dashboards/19423-hubble-l7-http-metrics-by-workload/">Hubble L7 HTTP Metrics — Grafana dashboard 19423&lt;/a> — listo para importar.&lt;/li>
&lt;li>&lt;a href="https://cloud-cod.com/index.php/2026/03/03/end-to-end-l7-visibility-with-cilium-hubble/">End‑to‑end L7 Visibility with Cilium Hubble (cloud-cod.com, mar 2026)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://www.youngju.dev/blog/cilium/cilium_hubble_observability.en">Cilium Hubble Observability Platform Internal Analysis (Young-ju)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://johal.in/ciliumnetworkpolicy-python-hubble-l7-visibility-2026/">CiliumNetworkPolicy Python Hubble: L7 Visibility 2026&lt;/a> — uno de los hilos del SDK Python.&lt;/li>
&lt;/ul>
&lt;p>Estado del arte 2026 y stack completo:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://dev.to/x4nent/building-a-production-ebpf-observability-security-stack-for-kubernetes-in-2026-5051">Building a Production eBPF Observability &amp;amp; Security Stack for Kubernetes in 2026 (DEV)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://www.cloudraft.io/blog/ebpf-based-network-observability-using-cilium-hubble">eBPF-Based Network Observability: Exploring Cilium Hubble and Alternatives (CloudRaft)&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>eBPF + agentes IA:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/eunomia-bpf/agentsight">AgentSight (GitHub eunomia-bpf)&lt;/a> — el proyecto referenciado.&lt;/li>
&lt;li>&lt;a href="https://klizosolutions.medium.com/harnessing-ebpf-for-high-performance-llm-workloads-a-cloud-native-guide-efb7d73e19ed">Harnessing eBPF for High‑Performance LLM Workloads (Klizo Solutions)&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>Cross-references:&lt;/p>
&lt;ul>
&lt;li>Parte 1: &lt;a href="https://blog.lo0.es/posts/ebpf-cilium-tcp-ip-bypass/">eBPF de cero a Cilium&lt;/a>.&lt;/li>
&lt;li>Parte 2: &lt;a href="https://blog.lo0.es/posts/tetragon-runtime-security/">Tetragon: el primo de seguridad de Cilium&lt;/a>.&lt;/li>
&lt;li>Serie de inferencia LLM: &lt;a href="https://blog.lo0.es/posts/kv-cache-fundamentos/">KV cache&lt;/a>, &lt;a href="https://blog.lo0.es/posts/vllm-kubernetes/">vLLM en K8s&lt;/a>, &lt;a href="https://blog.lo0.es/posts/pagedattention-deep-dive/">PagedAttention&lt;/a>, &lt;a href="https://blog.lo0.es/posts/operators-llm-kubernetes/">Operators LLM K8s&lt;/a> — donde el tráfico que Hubble observa lleva los prompts que AgentSight inspecciona.&lt;/li>
&lt;/ul></description></item><item><title>Tetragon: el primo de seguridad de Cilium que ve cada syscall en el kernel</title><link>https://blog.lo0.es/posts/tetragon-runtime-security/</link><pubDate>Tue, 19 May 2026 05:00:00 +0200</pubDate><guid>https://blog.lo0.es/posts/tetragon-runtime-security/</guid><description>&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>&lt;a href="https://tetragon.io/">Tetragon&lt;/a> es el motor de &lt;strong>seguridad y observabilidad de runtime&lt;/strong> que el proyecto Cilium publicó como complemento al CNI. Su trabajo no es enrutar paquetes —para eso ya está Cilium— sino &lt;strong>observar lo que pasa dentro de los procesos del nodo en tiempo real&lt;/strong>: qué binario se ejecuta en cada pod, qué archivos abre, qué syscalls invoca, qué capabilities pide, qué conexiones de red establece, qué módulos del kernel se cargan. Lo hace cargando programas eBPF en los &lt;strong>hook points&lt;/strong> del kernel (kprobes, tracepoints, uprobes, LSM hooks) y filtrando los eventos relevantes &lt;strong>dentro del propio kernel&lt;/strong> con un lenguaje declarativo expresado como CRD (&lt;code>TracingPolicy&lt;/code> y &lt;code>TracingPolicyNamespaced&lt;/code>). El resultado es un flujo de eventos enriquecidos con metadata Kubernetes (pod, namespace, labels) que cuesta &lt;strong>menos del 1% de CPU&lt;/strong> y, lo que diferencia a Tetragon de la competencia, puede &lt;strong>bloquear acciones dentro del kernel&lt;/strong> —matar el proceso con &lt;code>SIGKILL&lt;/code> o sobrescribir el retorno de un syscall— &lt;strong>antes de que terminen de ejecutarse&lt;/strong>, sin race conditions. Frente a Falco (que parsea syscalls en userspace, 5-10% overhead, detection-only), Tetragon es &amp;ldquo;más barato y con enforcement&amp;rdquo;; frente al kernel desnudo, es &amp;ldquo;una capa declarativa que tu compañero de operaciones puede leer&amp;rdquo;. Este artículo es la introducción extensa que necesitas para abordarlo en serio: arquitectura, todos los hooks y selectors, los modos de operación, una guía de casos de uso (auditoría de exec, acceso a archivos sensibles, container escape, cryptomining, detección de rootkits, observabilidad de red) y las trampas que se ven en producción.&lt;/p>
&lt;blockquote>
&lt;p>Este artículo es la &lt;strong>parte 2 de la serie sobre eBPF&lt;/strong>. La parte 1 —&lt;a href="https://blog.lo0.es/posts/ebpf-cilium-tcp-ip-bypass/">eBPF de cero a Cilium: cómo el kernel aprendió a saltarse su propia pila TCP/IP&lt;/a>— cubrió eBPF básico, los hooks de networking (XDP, TC, sock_ops), cómo Cilium implementa el datapath y los CRDs del BGP Control Plane v2. Aquí cogemos esos mismos hooks de eBPF y los usamos para algo distinto: &lt;strong>observar y, si hace falta, frenar&lt;/strong> lo que hacen los procesos del cluster.&lt;/p>
&lt;/blockquote>
&lt;h2 id="la-analogía-auditd-con-esteroides-en-ebpf">La analogía: auditd con esteroides en eBPF&lt;/h2>
&lt;p>Quien lleve unos años administrando Linux ha usado &lt;code>auditd&lt;/code>. Es el subsistema clásico del kernel para auditar syscalls: configuras una regla con &lt;code>auditctl&lt;/code> (por ejemplo, &amp;ldquo;monitoriza cualquier &lt;code>open&lt;/code> sobre &lt;code>/etc/shadow&lt;/code>&amp;rdquo;) y el kernel envía eventos a un daemon en userspace que los persiste. Funciona, pero tiene dos limitaciones que pesan en clusters Kubernetes modernos:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Sin contexto Kubernetes.&lt;/strong> auditd reporta procesos por PID y UID. Saber qué pod, qué namespace, qué imagen, qué labels —la información que de verdad importa para responder a un incidente— requiere correlar a posteriori con datos de cri-o o containerd. Es operacionalmente miserable.&lt;/li>
&lt;li>&lt;strong>Sin enforcement granular.&lt;/strong> auditd puede generar eventos, pero no puede tomar la decisión de matar el proceso ofensor antes de que termine la syscall. Eso lo dejas a una capa superior que lee los eventos, los procesa y mata el proceso… si llega a tiempo. Carrera por design.&lt;/li>
&lt;/ol>
&lt;p>Tetragon es &lt;strong>auditd con esteroides&lt;/strong>: las mismas ideas conceptuales —hooks en syscalls, eventos a userspace— pero implementadas con eBPF moderno, con filtrado dentro del kernel para no pagar el coste de despertar el daemon por cada syscall irrelevante, con metadata Kubernetes inyectada por un agente que conoce el cluster, y con &lt;strong>acciones que se ejecutan dentro del propio kernel&lt;/strong> sin esperar a que userspace decida. Si la regla dice &amp;ldquo;mata cualquier proceso que abra &lt;code>/etc/shadow&lt;/code> desde el namespace &lt;code>prod&lt;/code>&amp;rdquo;, la decisión se toma en el kprobe del kernel y &lt;code>SIGKILL&lt;/code> se entrega antes de que el &lt;code>open&lt;/code> se complete. No hay race; no hay ventana entre detección y acción.&lt;/p>
&lt;h2 id="qué-es-tetragon-arquitectónicamente">Qué es Tetragon, arquitectónicamente&lt;/h2>
&lt;p>Tetragon es &lt;strong>un agent&lt;/strong> que se despliega como &lt;code>DaemonSet&lt;/code> (un pod por nodo) y &lt;strong>un conjunto de CRDs&lt;/strong> que definen las políticas a aplicar. El agent tiene cuatro responsabilidades:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Cargar programas eBPF&lt;/strong> en los hook points que las TracingPolicies activas demanden.&lt;/li>
&lt;li>&lt;strong>Mantener un cache de metadata Kubernetes&lt;/strong> (pods, namespaces, labels) leyendo el API server, para poder enriquecer cada evento con el contexto correcto.&lt;/li>
&lt;li>&lt;strong>Recolectar los eventos&lt;/strong> que los programas eBPF emiten (vía ring buffers) y serializarlos.&lt;/li>
&lt;li>&lt;strong>Exportar los eventos&lt;/strong> a destinos configurables: &lt;code>stdout&lt;/code> JSON (típico en sidecars o agentes log-collection), gRPC streaming (para consumirlos desde Hubble u otro consumer), archivo, o Fluentd/Loki/SIEM.&lt;/li>
&lt;/ol>
&lt;p>Los programas eBPF no son escritos por el usuario. Tetragon genera el bytecode a partir de las TracingPolicies: lee la política declarativa, decide qué hooks atacar, qué argumentos leer del kernel, qué filtros aplicar en línea y qué acciones ejecutar. El usuario solo escribe &lt;strong>YAML&lt;/strong>.&lt;/p>
&lt;div class="diagram" style="max-width:720px;margin:1.5rem auto;">
&lt;svg viewBox="0 0 720 280" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Arquitectura de Tetragon">
&lt;style>.title{font:600 13px sans-serif;fill:#222}.lbl{font:600 12px sans-serif;fill:#222}.sm{font:11px sans-serif;fill:#555}.box{stroke:#444;stroke-width:1.4}.k{fill:#ffe9d6}.u{fill:#d6eaff}.p{fill:#d9f5d6}.api{fill:#e9d6f5}.arr{stroke:#666;stroke-width:1.4;fill:none;marker-end:url(#h)}&lt;/style>
&lt;defs>&lt;marker id="h" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">&lt;path d="M0,0 L10,5 L0,10 z" fill="#666"/>&lt;/marker>&lt;/defs>
&lt;text x="360" y="20" text-anchor="middle" class="title">Tetragon: planos de control y datos en un nodo&lt;/text>
&lt;rect x="40" y="50" width="200" height="70" rx="6" class="box k"/>
&lt;text x="140" y="70" text-anchor="middle" class="lbl">Programas eBPF&lt;/text>
&lt;text x="140" y="90" text-anchor="middle" class="sm">kprobes, tracepoints,&lt;/text>
&lt;text x="140" y="105" text-anchor="middle" class="sm">uprobes, LSM&lt;/text>
&lt;rect x="40" y="160" width="200" height="60" rx="6" class="box u"/>
&lt;text x="140" y="183" text-anchor="middle" class="lbl">Tetragon agent&lt;/text>
&lt;text x="140" y="203" text-anchor="middle" class="sm">recibe eventos del ring buffer&lt;/text>
&lt;rect x="290" y="160" width="180" height="60" rx="6" class="box api"/>
&lt;text x="380" y="183" text-anchor="middle" class="lbl">Kubernetes API&lt;/text>
&lt;text x="380" y="203" text-anchor="middle" class="sm">pods, namespaces, labels&lt;/text>
&lt;rect x="510" y="50" width="180" height="70" rx="6" class="box p"/>
&lt;text x="600" y="70" text-anchor="middle" class="lbl">TracingPolicy CRDs&lt;/text>
&lt;text x="600" y="90" text-anchor="middle" class="sm">YAML declarativo&lt;/text>
&lt;text x="600" y="105" text-anchor="middle" class="sm">cluster o namespaced&lt;/text>
&lt;rect x="510" y="160" width="180" height="60" rx="6" class="box u"/>
&lt;text x="600" y="183" text-anchor="middle" class="lbl">Exporters&lt;/text>
&lt;text x="600" y="203" text-anchor="middle" class="sm">stdout, gRPC, file, SIEM&lt;/text>
&lt;path class="arr" d="M510,80 L240,80"/>
&lt;text x="375" y="74" text-anchor="middle" class="sm">policies → bytecode&lt;/text>
&lt;path class="arr" d="M140,120 L140,160"/>
&lt;text x="160" y="143" text-anchor="middle" class="sm">eventos&lt;/text>
&lt;path class="arr" d="M290,190 L240,190"/>
&lt;text x="265" y="184" text-anchor="middle" class="sm">enrich&lt;/text>
&lt;path class="arr" d="M240,180 L510,180"/>
&lt;text x="375" y="174" text-anchor="middle" class="sm">eventos enriquecidos&lt;/text>
&lt;text x="360" y="255" text-anchor="middle" class="sm">Las flechas muestran flujo de datos. Las TracingPolicies se compilan en programas eBPF;&lt;/text>
&lt;text x="360" y="270" text-anchor="middle" class="sm">los eventos viajan kernel → agent → exporter, decorados con metadata K8s por el camino.&lt;/text>
&lt;/svg>
&lt;/div>
&lt;p>Esta separación &lt;strong>policy declarativa → bytecode eBPF generado&lt;/strong> es lo que hace a Tetragon usable. Escribir programas eBPF a mano es trabajo de un especialista; escribir una &lt;code>TracingPolicy&lt;/code> es trabajo de un SRE con un buen ejemplo a la vista.&lt;/p>
&lt;h2 id="los-dos-crds-tracingpolicy-y-tracingpolicynamespaced">Los dos CRDs: TracingPolicy y TracingPolicyNamespaced&lt;/h2>
&lt;p>Tetragon expone exactamente &lt;strong>dos CRDs principales&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>TracingPolicy&lt;/code>&lt;/strong> (cluster-scoped, &lt;code>cilium.io/v1alpha1&lt;/code>): se aplica a &lt;strong>todo el cluster&lt;/strong>, todos los nodos, todos los pods. Adecuada para políticas de plataforma (todo el cluster debe ser auditado igual): por ejemplo, &amp;ldquo;registra todo &lt;code>execve&lt;/code> en todos los pods&amp;rdquo; o &amp;ldquo;mata cualquier proceso que intente cargar un módulo del kernel&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>&lt;code>TracingPolicyNamespaced&lt;/code>&lt;/strong> (namespaced, mismo grupo y versión): se define dentro de un namespace y &lt;strong>solo se aplica a los pods de ese namespace&lt;/strong>. Adecuada para políticas con autonomía por tenant: por ejemplo, &amp;ldquo;en el namespace &lt;code>prod-payments&lt;/code>, mata cualquier &lt;code>connect&lt;/code> saliente a una IP fuera del rango corporativo&amp;rdquo;.&lt;/li>
&lt;/ul>
&lt;p>Ambos CRDs tienen exactamente la misma estructura interna. La diferencia es de scope. La distinción se introdujo precisamente para permitir multi-tenancy: que el equipo de seguridad central defina políticas &lt;code>TracingPolicy&lt;/code> cluster-wide y que cada tenant pueda añadir las suyas con &lt;code>TracingPolicyNamespaced&lt;/code> sin necesitar permisos cluster-admin.&lt;/p>
&lt;h2 id="anatomía-de-una-tracingpolicy">Anatomía de una TracingPolicy&lt;/h2>
&lt;p>Una política se compone de:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Hook points&lt;/strong>: qué eventos del kernel observar.&lt;/li>
&lt;li>&lt;strong>Argumentos&lt;/strong>: qué datos leer cuando el hook se dispara.&lt;/li>
&lt;li>&lt;strong>Selectors&lt;/strong>: filtros que se evalúan &lt;strong>dentro del kernel&lt;/strong> para descartar eventos no relevantes y, opcionalmente, ejecutar acciones cuando coinciden.&lt;/li>
&lt;/ol>
&lt;h3 id="hook-points-soportados">Hook points soportados&lt;/h3>
&lt;p>La documentación oficial enumera cinco familias de hook points:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>kprobes&lt;/code>&lt;/strong>: hookean una función del kernel. Las syscalls son un caso particular (cuando &lt;code>syscall: true&lt;/code>) porque su ABI es distinta del de las funciones internas. Ejemplos típicos: &lt;code>sys_open&lt;/code>, &lt;code>sys_openat&lt;/code>, &lt;code>sys_connect&lt;/code>, &lt;code>tcp_connect&lt;/code>, &lt;code>do_mount&lt;/code>, &lt;code>commit_creds&lt;/code>. Es el hook más versátil y el que se usa el 80% del tiempo.&lt;/li>
&lt;li>&lt;strong>&lt;code>tracepoints&lt;/code>&lt;/strong>: hookean tracepoints estáticos compilados en el kernel. Más estables entre versiones de kernel que los kprobes (no dependen de nombres de funciones que pueden cambiar). Ejemplos: &lt;code>syscalls/sys_enter_openat&lt;/code>, &lt;code>sched/sched_process_exec&lt;/code>.&lt;/li>
&lt;li>&lt;strong>&lt;code>uprobes&lt;/code>&lt;/strong>: hookean funciones de bibliotecas o binarios en userspace. Sirven para observar primitivas de runtime como funciones de libssl, libc, Go runtime, JVM.&lt;/li>
&lt;li>&lt;strong>&lt;code>tracepoints&lt;/code> USDT&lt;/strong> (User Statically Defined Tracepoints): tracepoints estáticos definidos en binarios userspace (como los que MySQL, PostgreSQL, OpenJDK exponen). Útiles para observabilidad de aplicaciones.&lt;/li>
&lt;li>&lt;strong>&lt;code>lsmHooks&lt;/code>&lt;/strong> (LSM, Linux Security Module): hooks del subsistema LSM, donde se enchufa SELinux/AppArmor. Permiten políticas de seguridad muy similares a las de MAC tradicional pero programables con eBPF. Ejemplo: &lt;code>file_open&lt;/code>, &lt;code>inode_unlink&lt;/code>, &lt;code>socket_bind&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="argumentos">Argumentos&lt;/h3>
&lt;p>Cada hook puede leer los argumentos de la función a la que está atado. Los tipos soportados cubren los primitivos (&lt;code>int&lt;/code>, &lt;code>uint64&lt;/code>, &lt;code>bool&lt;/code>, &lt;code>string&lt;/code>, &lt;code>char_buf&lt;/code>) y abstracciones más altas (&lt;code>file&lt;/code>, &lt;code>path&lt;/code>, &lt;code>sock&lt;/code>, &lt;code>linux_binprm&lt;/code>, &lt;code>capability&lt;/code>, &lt;code>bpf_attr&lt;/code>, &lt;code>cred&lt;/code>). Los tipos altos son punteros a estructuras del kernel que Tetragon sabe parsear; en lugar de tener que leer un offset, escribes &lt;code>type: file&lt;/code> y Tetragon te da el path completo del archivo del descriptor.&lt;/p>
&lt;p>Hay un detalle importante de capacidad: en kernels &lt;strong>≥ 5.4&lt;/strong>, Tetragon puede leer &lt;strong>hasta 327 360 bytes&lt;/strong> de un argumento si se activa el flag de buffers grandes. Es la diferencia entre poder auditar &lt;code>execve&lt;/code> con todos sus argv largos completos vs truncarlos a 256 bytes y perder contexto.&lt;/p>
&lt;h3 id="selectors-filtrado-en-el-kernel">Selectors: filtrado en el kernel&lt;/h3>
&lt;p>Los selectors son lo que hace a Tetragon barato. Sin ellos, &lt;strong>cada syscall&lt;/strong> del nodo dispararía un evento que viajaría kernel → ring buffer → agent → procesado → filtrado → descartado. Con selectors, el filtrado ocurre &lt;strong>dentro del propio programa eBPF, en el kernel&lt;/strong>, y solo los eventos que importan llegan al userspace.&lt;/p>
&lt;p>Los selectors disponibles incluyen:&lt;/p>
&lt;ul>
&lt;li>&lt;code>matchArgs&lt;/code>: filtra por el valor de un argumento. Operadores: &lt;code>Equal&lt;/code>, &lt;code>NotEqual&lt;/code>, &lt;code>Prefix&lt;/code>, &lt;code>Postfix&lt;/code>, &lt;code>GreaterThan&lt;/code>, &lt;code>LessThan&lt;/code>, &lt;code>Mask&lt;/code>, &lt;code>SPort&lt;/code> (source port), &lt;code>DPort&lt;/code> (dest port), &lt;code>Family&lt;/code> (AF_INET vs AF_INET6), &lt;code>State&lt;/code> (estado del socket).&lt;/li>
&lt;li>&lt;code>matchPIDs&lt;/code>: filtra por PID; útil para targeted observation.&lt;/li>
&lt;li>&lt;code>matchBinaries&lt;/code>: filtra por el binario que ejecuta el syscall (path absoluto), con &lt;code>Operator: In&lt;/code>, &lt;code>NotIn&lt;/code>, &lt;code>Prefix&lt;/code>. Imprescindible para evitar el ruido de procesos legítimos del sistema.&lt;/li>
&lt;li>&lt;code>matchNamespaces&lt;/code>: filtra por namespace Linux (Pid, Mnt, Net, Ipc, Cgroup, User). Permite políticas específicas para procesos en contenedores vs el host.&lt;/li>
&lt;li>&lt;code>matchCapabilities&lt;/code>: filtra por capabilities efectivas del proceso. Bloquear acciones que requieran &lt;code>CAP_SYS_ADMIN&lt;/code> que se ejecuten en pods que no deberían tenerlas.&lt;/li>
&lt;li>&lt;code>matchNamespaceChanges&lt;/code>: detecta cambios de namespace (típico de container escape).&lt;/li>
&lt;li>&lt;code>matchCapabilityChanges&lt;/code>: detecta cambios de capabilities (escalada de privilegios).&lt;/li>
&lt;li>&lt;code>matchActions&lt;/code>: las acciones que se ejecutan cuando todos los matchers anteriores aciertan.&lt;/li>
&lt;/ul>
&lt;h3 id="acciones-del-simple-post-al-sigkill">Acciones: del simple Post al Sigkill&lt;/h3>
&lt;p>Cuando un selector matchea, se ejecuta una &lt;code>action&lt;/code>. Tetragon define varias:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>Post&lt;/code>&lt;/strong>: emite un evento al userspace (el caso de observability). Soporta &lt;code>rateLimit&lt;/code> para evitar inundar el agent si la condición se dispara mil veces por segundo. La sintaxis acepta &lt;code>5&lt;/code> para 5 segundos, &lt;code>5m&lt;/code> para 5 minutos, &lt;code>1h&lt;/code> para 1 hora.&lt;/li>
&lt;li>&lt;strong>&lt;code>Sigkill&lt;/code>&lt;/strong>: envía &lt;code>SIGKILL&lt;/code> al proceso ofensor desde dentro del kernel, &lt;strong>antes de que la syscall complete&lt;/strong>. Esto es lo único que garantiza enforcement sin race.&lt;/li>
&lt;li>&lt;strong>&lt;code>Override&lt;/code>&lt;/strong>: sobrescribe el valor de retorno del syscall. Útil para hacer creer al proceso que el syscall falló (&lt;code>Override -EPERM&lt;/code>) sin matarlo. Mejor experiencia para apps que pueden manejar errores; peor para apps que asumen éxito.&lt;/li>
&lt;li>&lt;strong>&lt;code>Signal&lt;/code>&lt;/strong>: envía cualquier señal arbitraria (no solo &lt;code>SIGKILL&lt;/code>).&lt;/li>
&lt;li>&lt;strong>&lt;code>NoPost&lt;/code>&lt;/strong>: no emite evento, útil cuando se combina con otro selector que sí emite y solo quieres acción sin telemetría duplicada.&lt;/li>
&lt;li>&lt;strong>&lt;code>FollowFD&lt;/code> y &lt;code>UnfollowFD&lt;/code>&lt;/strong>: marcan un file descriptor para seguir su ciclo de vida y enriquecer eventos siguientes con el path original. Útil para audit de &amp;ldquo;qué proceso leyó este archivo después de abrirlo&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>&lt;code>TrackSock&lt;/code>&lt;/strong> y &lt;strong>&lt;code>UntrackSock&lt;/code>&lt;/strong>: idem para sockets.&lt;/li>
&lt;li>&lt;strong>&lt;code>GetUrl&lt;/code> y &lt;code>DnsLookup&lt;/code>&lt;/strong>: hacen peticiones HTTP o resoluciones DNS desde el kernel. Pensado para integraciones con sistemas externos (webhooks de seguridad, lookups de reputación de IP).&lt;/li>
&lt;li>&lt;strong>&lt;code>NotifyEnforcer&lt;/code>&lt;/strong> y &lt;strong>&lt;code>CleanupEnforcerNotification&lt;/code>&lt;/strong>: comunicación con el subsistema de enforcement de Tetragon para acciones complejas.&lt;/li>
&lt;/ul>
&lt;h2 id="modos-detection-vs-enforcement">Modos: detection vs enforcement&lt;/h2>
&lt;p>Una política se puede declarar en uno de dos &lt;strong>modos&lt;/strong> explícitos:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>enforce&lt;/code>&lt;/strong>: las acciones de enforcement (&lt;code>Sigkill&lt;/code>, &lt;code>Override&lt;/code>, &lt;code>Signal&lt;/code>) están activas. Esto es producción.&lt;/li>
&lt;li>&lt;strong>&lt;code>monitoring&lt;/code>&lt;/strong>: las acciones de enforcement son ignoradas; solo se emiten eventos &lt;code>Post&lt;/code>. Esto es el modo &amp;ldquo;vamos a ver qué pasaría si esto estuviese activado&amp;rdquo;, crítico para probar políticas sin romper aplicaciones.&lt;/li>
&lt;/ul>
&lt;p>El control se hace con el campo &lt;code>spec.options[].name: policy-mode&lt;/code> y &lt;code>value: monitoring&lt;/code> o &lt;code>enforce&lt;/code>. Es la mejor práctica: empezar en &lt;code>monitoring&lt;/code>, recolectar eventos durante días, ajustar los selectors hasta que no salgan falsos positivos, &lt;strong>y entonces&lt;/strong> cambiar a &lt;code>enforce&lt;/code>.&lt;/p>
&lt;h2 id="ejemplo-completo-bloquear-escrituras-a-etcpasswd-en-namespace-prod">Ejemplo completo: bloquear escrituras a &lt;code>/etc/passwd&lt;/code> en namespace prod&lt;/h2>
&lt;p>Una política realista, comentada línea a línea:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v1alpha1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TracingPolicyNamespaced&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">block-passwd-write&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">namespace&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">prod&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kprobes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">call&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;fd_install&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">syscall&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># función del kernel, no syscall&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">int &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># file descriptor&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;file&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># struct file*&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchArgs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Equal&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/etc/passwd&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Sigkill &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># mata el proceso&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">rateLimit&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;1m&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># max una vez por minuto&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">options&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">policy-mode&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">enforce &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># modo enforcement activo&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>fd_install&lt;/code> se ejecuta cada vez que un proceso obtiene un nuevo file descriptor; el segundo argumento es la struct &lt;code>file&lt;/code> del archivo. Tetragon sabe resolverla a su path absoluto. El &lt;code>matchArgs&lt;/code> compara ese path con &lt;code>/etc/passwd&lt;/code>. Si matchea, &lt;code>Sigkill&lt;/code> mata el proceso antes de que el descriptor llegue siquiera a ser usable. &lt;code>rateLimit: 1m&lt;/code> impide que el agent se sature si una aplicación malintencionada lo intenta en bucle.&lt;/p>
&lt;h2 id="casos-de-uso-habituales">Casos de uso habituales&lt;/h2>
&lt;p>Vamos al uso real. Estos son los seis casos que aparecen en cualquier despliegue serio de Tetragon en 2026.&lt;/p>
&lt;h3 id="1-auditoría-de-ejecución-execve">1. Auditoría de ejecución (&lt;code>execve&lt;/code>)&lt;/h3>
&lt;p>El caso de uso más básico y, sin embargo, el más valioso. ¿Qué binarios se están ejecutando en cada pod? En un container que se supone que corre solo &lt;code>nginx&lt;/code>, ver de pronto un &lt;code>sh&lt;/code> o un &lt;code>wget&lt;/code> es bandera roja casi siempre.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v1alpha1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TracingPolicy&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">audit-execve&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">tracepoints&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">subsystem&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;sched&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">event&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;sched_process_exec&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">4&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">linux_binprm &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># struct linux_binprm*&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Post &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># solo eventos, no enforcement&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Sin filtros: cada &lt;code>execve&lt;/code> del cluster genera un evento. Con metadata K8s, el evento incluye pod, namespace, container, imagen, labels. Lo conviertes en flujo de eventos hacia tu SIEM y montas reglas: &amp;ldquo;alerta si veo &lt;code>sh&lt;/code>, &lt;code>bash&lt;/code>, &lt;code>nc&lt;/code>, &lt;code>curl&lt;/code>, &lt;code>wget&lt;/code>, &lt;code>python&lt;/code> ejecutándose en cualquier pod del namespace &lt;code>prod-api&lt;/code>&amp;rdquo;.&lt;/p>
&lt;p>Variación con enforcement: en lugar de &lt;code>Post&lt;/code>, usar &lt;code>matchBinaries&lt;/code> con &lt;code>Operator: NotIn&lt;/code> y una whitelist, y &lt;code>Sigkill&lt;/code> si el binario no está en la lista. Caja muy rígida pero efectiva en pods que son &amp;ldquo;single-binary&amp;rdquo; (como un microservicio Go).&lt;/p>
&lt;h3 id="2-acceso-a-archivos-sensibles">2. Acceso a archivos sensibles&lt;/h3>
&lt;p>Detectar (o bloquear) lecturas y escrituras a archivos críticos: &lt;code>/etc/shadow&lt;/code>, &lt;code>/etc/kubernetes/&lt;/code>, montajes de Secrets, &lt;code>/var/run/docker.sock&lt;/code>, &lt;code>/proc/*/cmdline&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v1alpha1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TracingPolicy&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">sensitive-file-access&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kprobes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">call&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;security_file_open&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># LSM-ish via kprobe&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">syscall&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;file&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchArgs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Prefix&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/etc/shadow&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/var/run/secrets/&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/var/run/docker.sock&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchBinaries&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;NotIn&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/usr/bin/kubelet&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># acceso legítimo de kubelet&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Post&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>El &lt;code>matchBinaries: NotIn&lt;/code> es importante: kubelet y otros agentes legítimos del nodo acceden a estos paths constantemente y generarían ruido. Filtramos esos en el kernel.&lt;/p>
&lt;p>En enforcement: cambiar &lt;code>Post&lt;/code> por &lt;code>Override&lt;/code> con &lt;code>argError: -1&lt;/code> (&lt;code>EPERM&lt;/code>), de modo que la apertura falle pero el proceso ofensor siga vivo y produzca el error para que las herramientas de tracing lo recojan.&lt;/p>
&lt;h3 id="3-conexiones-de-red-salientes-no-autorizadas">3. Conexiones de red salientes no autorizadas&lt;/h3>
&lt;p>Detectar conexiones outbound a destinos fuera del rango corporativo. Útil para detectar exfiltración de datos o command-and-control de malware.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v1alpha1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TracingPolicyNamespaced&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">block-external-egress&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">namespace&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">prod&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kprobes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">call&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;tcp_connect&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">syscall&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;sock&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchArgs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;NotDAddr&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># destino NO en estos CIDRs&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;10.0.0.0/8&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;192.168.0.0/16&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;172.16.0.0/12&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Sigkill&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">options&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">policy-mode&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">enforce&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Esto mata cualquier intento de conexión TCP a una IP que no esté en los CIDRs corporativos, en namespace &lt;code>prod&lt;/code>. Cilium ya hace esto con NetworkPolicy, pero Tetragon tiene dos ventajas complementarias:&lt;/p>
&lt;ul>
&lt;li>Te da el &lt;strong>proceso&lt;/strong> que intentó la conexión, no solo &amp;ldquo;el pod X intentó conectar a Y&amp;rdquo;.&lt;/li>
&lt;li>Funciona también para protocolos exóticos donde NetworkPolicy es menos expresiva.&lt;/li>
&lt;/ul>
&lt;h3 id="4-detección-de-container-escape">4. Detección de container escape&lt;/h3>
&lt;p>Container escape es la pesadilla operacional: un proceso dentro de un contenedor consigue romper el aislamiento (vía un kernel exploit, una capability mal puesta, un mount &lt;code>hostPath&lt;/code> mal configurado) y obtener acceso al host. Tres señales típicas:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Cambio de namespace&lt;/strong> del proceso (sale del namespace &lt;code>pid&lt;/code> del contenedor).&lt;/li>
&lt;li>&lt;strong>&lt;code>setns&lt;/code> o &lt;code>unshare&lt;/code>&lt;/strong> en procesos no-init.&lt;/li>
&lt;li>&lt;strong>Acceso a &lt;code>/proc/1/root&lt;/code> o &lt;code>/dev/&lt;/code>&lt;/strong> desde un contenedor.&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v1alpha1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TracingPolicy&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">detect-container-escape&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kprobes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">call&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;__x64_sys_setns&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">syscall&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">int&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">int&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchNamespaces&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">namespace&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Pid&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">NotIn&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;host_ns&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># solo procesos NO en pid namespace del host&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Sigkill&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">call&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;__x64_sys_unshare&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">syscall&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">int&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchNamespaceChanges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">unshare&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Post&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>__x64_sys_setns&lt;/code> con destino el namespace del host desde un proceso en contenedor es prácticamente siempre malicioso (los containers legítimos no necesitan esto en runtime).&lt;/p>
&lt;h3 id="5-cryptomining">5. Cryptomining&lt;/h3>
&lt;p>Los procesos de minería tienen perfiles bastante reconocibles:&lt;/p>
&lt;ul>
&lt;li>Procesos con nombres como &lt;code>xmrig&lt;/code>, &lt;code>minerd&lt;/code>, &lt;code>cgminer&lt;/code>, o procesos legítimos como &lt;code>python&lt;/code> ejecutando scripts con uso intensivo de CPU.&lt;/li>
&lt;li>Conexiones outbound a pools de minería conocidas (lista pública de IPs y dominios).&lt;/li>
&lt;li>Uso anómalo de &lt;code>/dev/cpu_dma_latency&lt;/code> para evitar throttling.&lt;/li>
&lt;/ul>
&lt;p>Una política combinada:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v1alpha1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TracingPolicy&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">detect-cryptomining&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">tracepoints&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">subsystem&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;sched&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">event&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;sched_process_exec&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">4&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">linux_binprm&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchArgs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">4&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Postfix&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/xmrig&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/minerd&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/cgminer&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Sigkill&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kprobes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">call&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;tcp_connect&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">syscall&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;sock&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchArgs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;DPort&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;3333&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;5555&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;7777&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;14444&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># puertos comunes de pools&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Post &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># solo registra&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>La doble política: matar binarios con nombres clásicos (cinturón) y registrar conexiones a puertos de pools (tirantes), para alertar también cuando alguien renombre &lt;code>xmrig&lt;/code> a &lt;code>nginx-helper&lt;/code> o use puertos exóticos.&lt;/p>
&lt;h3 id="6-detección-de-rootkits-y-módulos-del-kernel-sospechosos">6. Detección de rootkits y módulos del kernel sospechosos&lt;/h3>
&lt;p>Los rootkits modernos cargan módulos del kernel para parchear funciones (hide procesos, hide conexiones de red, esconder archivos). Detectarlos:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v1alpha1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TracingPolicy&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">kernel-module-load&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kprobes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">call&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;do_init_module&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">syscall&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;string&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Post&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">call&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;security_kernel_read_file&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">syscall&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;file&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">int&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchArgs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Equal&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;READING_MODULE&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Post&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>En un cluster Kubernetes &amp;ldquo;bien configurado&amp;rdquo; no se cargan módulos nuevos del kernel en runtime; cualquier evento aquí es altamente sospechoso. Combina con enforcement para máquinas donde los módulos deberían estar fijos: &lt;code>Sigkill&lt;/code> al que intenta cargar uno.&lt;/p>
&lt;h3 id="bonus-detección-de-modificación-de-ebpf-maps-por-terceros">Bonus: detección de modificación de eBPF maps por terceros&lt;/h3>
&lt;p>Como tendencia 2025-2026: cargar programas eBPF maliciosos para esconder presencia. Tetragon puede observar el bpf syscall:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v1alpha1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TracingPolicy&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">audit-bpf-syscalls&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kprobes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">call&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;__x64_sys_bpf&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">syscall&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">int &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># bpf cmd&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">index&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">bpf_attr&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selectors&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">matchBinaries&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;NotIn&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/usr/bin/cilium-agent&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/usr/bin/tetragon&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/usr/bin/bpftool&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchActions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">action&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Post&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Cualquier proceso que &lt;strong>no sea&lt;/strong> uno de los agentes legítimos cargando programas eBPF: te interesa saberlo.&lt;/p>
&lt;h2 id="comparativa-con-falco">Comparativa con Falco&lt;/h2>
&lt;p>&lt;a href="https://falco.org/">Falco&lt;/a> es el competidor más cercano: también es &lt;strong>runtime security para Kubernetes&lt;/strong>, también basado originalmente en eBPF (y antes en kernel modules), también con políticas declarativas. Tres años atrás eran funcionalmente parecidos. En 2026 la divergencia es clara:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Dimensión&lt;/th>
&lt;th>Tetragon&lt;/th>
&lt;th>Falco&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Filosofía&lt;/td>
&lt;td>Cilium-native, integrado&lt;/td>
&lt;td>Standalone, genérico&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Filtrado&lt;/td>
&lt;td>En el kernel (eBPF)&lt;/td>
&lt;td>Parsing en userspace&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Overhead típico&lt;/td>
&lt;td>&lt;strong>&amp;lt;1% CPU&lt;/strong>&lt;/td>
&lt;td>5-10% CPU&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Enforcement&lt;/td>
&lt;td>&lt;strong>Sí, in-kernel (Sigkill, Override)&lt;/strong>&lt;/td>
&lt;td>No nativo (depende de plugins)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Race conditions&lt;/td>
&lt;td>No (acción atómica con syscall)&lt;/td>
&lt;td>Sí en enforcement vía plugins&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Detección de falsos positivos&lt;/td>
&lt;td>Baja (contexto K8s en kernel)&lt;/td>
&lt;td>Más alta (parsing posterior)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Latencia de detección&lt;/td>
&lt;td>5-26 ms&lt;/td>
&lt;td>~10 ms (más constante)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Madurez del ecosistema&lt;/td>
&lt;td>Joven, en crecimiento&lt;/td>
&lt;td>Maduro, mucho material&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Comunidad&lt;/td>
&lt;td>Cilium / CNCF Incubating&lt;/td>
&lt;td>CNCF Graduated&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Integraciones&lt;/td>
&lt;td>Hubble nativo&lt;/td>
&lt;td>Falcosidekick, muchas&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>CRDs por política&lt;/td>
&lt;td>TracingPolicy / Namespaced&lt;/td>
&lt;td>Sin CRDs; reglas en YAML&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Cuándo elegir cada uno&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Tetragon&lt;/strong> si ya usas Cilium, si necesitas enforcement en el kernel (no detection-only), si el overhead te importa (cargas con muchas syscalls), y si valoras la integración con Hubble. Detección de container escape y cryptomining es donde más se mide su ventaja sobre Falco.&lt;/li>
&lt;li>&lt;strong>Falco&lt;/strong> si quieres una herramienta independiente del CNI, si necesitas el catálogo de reglas pre-hechas y la comunidad amplia, si tu cluster no es Cilium, o si la integración con SIEMs y notificadores ya hechos (Falcosidekick) te ahorra trabajo.&lt;/li>
&lt;li>&lt;strong>Los dos&lt;/strong> si la organización es grande: Falco para amplitud de detección, Tetragon para enforcement quirúrgico en cargas críticas. Es lo que más se ve en empresas que llevan años con Falco y añaden Tetragon para casos específicos.&lt;/li>
&lt;/ul>
&lt;h2 id="hubble--tetragon-observabilidad-unificada">Hubble + Tetragon: observabilidad unificada&lt;/h2>
&lt;p>&lt;a href="https://docs.cilium.io/en/stable/observability/hubble/">Hubble&lt;/a> es el componente de observabilidad de tráfico de Cilium: muestra flow logs L3-L7 con cero impacto en latencia. Tetragon expone sus eventos por &lt;strong>gRPC&lt;/strong> con el mismo formato y vocabulario que Hubble, lo que permite:&lt;/p>
&lt;ul>
&lt;li>Verlos en la misma UI (Hubble UI muestra eventos Tetragon como una &amp;ldquo;capa&amp;rdquo; más).&lt;/li>
&lt;li>Correlar eventos de red (Hubble) con eventos de proceso (Tetragon) en el mismo timeline.&lt;/li>
&lt;li>Exportarlos juntos a Loki/Tempo/SIEM como un flujo único.&lt;/li>
&lt;/ul>
&lt;p>La sinergia clave: Hubble te dice &amp;ldquo;este pod hizo una conexión TCP a 1.2.3.4:80&amp;rdquo;. Tetragon te dice &amp;ldquo;este pod ejecutó &lt;code>curl 1.2.3.4&lt;/code> desde un binario &lt;code>bash&lt;/code> lanzado por &lt;code>pid 1234&lt;/code>&amp;rdquo;. Juntos te dan la historia completa.&lt;/p>
&lt;h2 id="despliegue-y-operación">Despliegue y operación&lt;/h2>
&lt;h3 id="helm">Helm&lt;/h3>
&lt;p>Instalación canónica con Helm:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">helm repo add cilium https://helm.cilium.io
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">helm install tetragon cilium/tetragon &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --namespace kube-system &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --set tetragon.exportFilename&lt;span class="o">=&lt;/span>/var/log/tetragon/tetragon.log &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --set tetragon.exportFileMaxSizeMB&lt;span class="o">=&lt;/span>&lt;span class="m">50&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --set tetragon.exportFileRotationInterval&lt;span class="o">=&lt;/span>24h
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Tetragon despliega su &lt;code>DaemonSet&lt;/code>, sus CRDs y un service para Hubble. Por defecto, expone los eventos en &lt;code>stdout&lt;/code> del pod del agent (los recoge cualquier log aggregator del cluster).&lt;/p>
&lt;h3 id="cli-tetra">CLI &lt;code>tetra&lt;/code>&lt;/h3>
&lt;p>Tetragon trae una CLI llamada &lt;code>tetra&lt;/code> para investigación interactiva:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># stream en tiempo real de eventos del nodo&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">tetra getevents -o compact --pods &amp;lt;pod-name&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># events JSON estructurado para procesar con jq&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">tetra getevents -o json --since 5m --namespace prod
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ver políticas cargadas&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">tetra tracingpolicy list
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Es la mejor herramienta para depurar políticas en &lt;code>monitoring&lt;/code> antes de pasarlas a &lt;code>enforce&lt;/code>.&lt;/p>
&lt;h3 id="exportar-a-siem">Exportar a SIEM&lt;/h3>
&lt;p>Tres rutas habituales:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>stdout + log aggregator&lt;/strong>: el agent escribe JSON al stdout, Fluent Bit/Vector lo recoge y lo envía a Splunk/Datadog/Elastic. Simple, funciona con cualquier infraestructura de logging.&lt;/li>
&lt;li>&lt;strong>gRPC streaming&lt;/strong>: para integraciones de baja latencia. Un consumer gRPC propio o Hubble Relay.&lt;/li>
&lt;li>&lt;strong>Archivo + rotación&lt;/strong>: para entornos air-gapped o auditorías regulatorias que exigen logs persistentes con rotación controlada.&lt;/li>
&lt;/ul>
&lt;h3 id="performance">Performance&lt;/h3>
&lt;p>Los benchmarks publicados consistentemente sitúan a Tetragon en &lt;strong>&amp;lt;1% de CPU&lt;/strong> del nodo en cargas reales, comparado con &lt;strong>5-10% de Falco&lt;/strong> en las mismas cargas. La razón es la separación arquitectónica: Tetragon filtra en el kernel y solo lleva a userspace los eventos que realmente importan; Falco lleva todos los syscalls a userspace y los filtra allí. En clusters con miles de pods haciendo cientos de miles de syscalls por segundo, la diferencia se nota en la factura.&lt;/p>
&lt;h2 id="trampas-operativas-comunes">Trampas operativas comunes&lt;/h2>
&lt;h3 id="monitoring-permanente">&lt;code>monitoring&lt;/code> permanente&lt;/h3>
&lt;p>La mayor trampa es &lt;strong>no llegar nunca a &lt;code>enforce&lt;/code>&lt;/strong>: empezar bien con políticas en monitoring, recolectar eventos, ajustar selectors, y luego nunca conmutar. Resultado: tienes detection sin prevention, exactamente lo que Falco te daba sin pagar la complejidad de Tetragon. Si vas a usar Tetragon, planifica el camino a enforce de las políticas críticas.&lt;/p>
&lt;h3 id="selectors-demasiado-laxos">Selectors demasiado laxos&lt;/h3>
&lt;p>Una política con un único &lt;code>matchActions: Post&lt;/code> sin selectors específicos genera eventos por &lt;strong>cada&lt;/strong> syscall del hook elegido. En un nodo serio son &lt;strong>decenas de miles por segundo&lt;/strong>, que llenan logs, saturan exporters y esconden la señal en el ruido. Empieza siempre con filtros estrictos (&lt;code>matchBinaries&lt;/code>, &lt;code>matchNamespaces&lt;/code>, &lt;code>matchPIDs&lt;/code>) y abre cuando sepas qué buscas.&lt;/p>
&lt;h3 id="kernel-demasiado-viejo">Kernel demasiado viejo&lt;/h3>
&lt;p>Tetragon necesita features de eBPF modernas. Kernels &amp;lt; 5.4 no tienen el soporte de buffers grandes (necesario para &lt;code>execve&lt;/code> con argv completos). Kernels &amp;lt; 5.10 no tienen muchos de los hooks LSM. &lt;strong>Kernel 5.15+ es el mínimo recomendado para producción&lt;/strong> y 6.1+ para tener todas las features.&lt;/p>
&lt;h3 id="hooks-en-funciones-del-kernel-renombradas">Hooks en funciones del kernel renombradas&lt;/h3>
&lt;p>Los kprobes están atados a nombres de funciones del kernel que &lt;strong>pueden cambiar entre versiones&lt;/strong>. Una política que use &lt;code>__x64_sys_setns&lt;/code> puede fallar silenciosamente en un kernel donde la función se llama &lt;code>__do_sys_setns&lt;/code>. Soluciones: usar tracepoints estáticos cuando estén disponibles (más estables), o tener políticas alternativas con varios &lt;code>call&lt;/code> por compatibilidad.&lt;/p>
&lt;h3 id="sigkill-en-namespaces-críticos">&lt;code>Sigkill&lt;/code> en namespaces críticos&lt;/h3>
&lt;p>Aplicar &lt;code>Sigkill&lt;/code> a procesos en &lt;code>kube-system&lt;/code> o &lt;code>cilium-system&lt;/code> puede romper el cluster. Las políticas de enforcement deben &lt;strong>excluir explícitamente&lt;/strong> los namespaces de plataforma con &lt;code>matchNamespaces&lt;/code> Operator: &lt;code>NotIn&lt;/code>, o limitar el scope con &lt;code>TracingPolicyNamespaced&lt;/code> para asegurar que no acciona en sistemas que no debe.&lt;/p>
&lt;h3 id="ratelimit-ausente">&lt;code>rateLimit&lt;/code> ausente&lt;/h3>
&lt;p>Una política sin rateLimit en &lt;code>Post&lt;/code> puede sufrir un fan-out catastrófico si la condición se cumple millones de veces en un instante (típico en bucles de ataque o en bugs de aplicación). El agent se satura, los eventos se pierden, los logs se desbordan. &lt;strong>Pon siempre &lt;code>rateLimit&lt;/code> sensato en políticas de detección&lt;/strong>, especialmente en hooks de alta frecuencia como &lt;code>tcp_connect&lt;/code> o &lt;code>execve&lt;/code>.&lt;/p>
&lt;h2 id="lo-que-no-hemos-cubierto-próximos-artículos">Lo que no hemos cubierto (próximos artículos)&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>eBPF LSM hooks&lt;/strong> en profundidad: cómo se relacionan con SELinux/AppArmor y cuándo Tetragon es la herramienta correcta vs MAC clásico.&lt;/li>
&lt;li>&lt;strong>Hubble UI con Tetragon overlay&lt;/strong>: configuración de la UI para mostrar la observabilidad de proceso y la de red en el mismo timeline.&lt;/li>
&lt;li>&lt;strong>Integración con OPA/Kyverno&lt;/strong>: cómo Tetragon complementa policy engines de admission (Kyverno valida en admission; Tetragon valida en runtime).&lt;/li>
&lt;li>&lt;strong>Forensics con eBPF&lt;/strong>: combinando Tetragon con herramientas como Beyla u OpenTelemetry para trazar la cadena completa de un incidente desde la conexión inicial hasta la syscall final.&lt;/li>
&lt;/ul>
&lt;h2 id="referencias">Referencias&lt;/h2>
&lt;p>Documentación oficial (mayo 2026):&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://tetragon.io/">Tetragon — sitio oficial&lt;/a> — punto de entrada.&lt;/li>
&lt;li>&lt;a href="https://tetragon.io/docs/concepts/tracing-policy/">Tetragon docs — Tracing Policy&lt;/a> — referencia conceptual.&lt;/li>
&lt;li>&lt;a href="https://tetragon.io/docs/concepts/tracing-policy/hooks/">Tetragon docs — Hook points&lt;/a> — kprobes, tracepoints, uprobes, LSM, USDT.&lt;/li>
&lt;li>&lt;a href="https://tetragon.io/docs/concepts/tracing-policy/selectors/">Tetragon docs — Selectors&lt;/a> — referencia completa de filtros.&lt;/li>
&lt;li>&lt;a href="https://tetragon.io/docs/concepts/tracing-policy/mode/">Tetragon docs — Enforcement Mode&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://tetragon.io/docs/concepts/tracing-policy/k8s-filtering/">Tetragon docs — Kubernetes Identity Aware Policies&lt;/a> — &lt;code>TracingPolicyNamespaced&lt;/code>.&lt;/li>
&lt;li>&lt;a href="https://github.com/cilium/tetragon">Tetragon GitHub&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>Comparativas y análisis:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.scitepress.org/Papers/2025/142727/142727.pdf">Comparative Analysis of eBPF-Based Runtime Security Monitoring (paper SciTePress 2025)&lt;/a> — benchmark con números independientes.&lt;/li>
&lt;li>&lt;a href="https://www.armosec.io/blog/best-ebpf-security-solutions-runtime-protection/">Best eBPF Security Solutions for Kubernetes (ARMO, 2026)&lt;/a> — comparativa Falco vs Tetragon vs KubeArmor.&lt;/li>
&lt;li>&lt;a href="https://medium.com/@mughal.asim/falco-vs-tetragon-a-runtime-security-showdown-for-kubernetes-a0e9fb9f30a0">Falco vs. Tetragon (Asim Mirza, Medium)&lt;/a> — análisis con casos de uso.&lt;/li>
&lt;li>&lt;a href="https://asecurityengineer.com/posts/deep-dive-into-tetragon/">Deep Dive into Tetragon (A Security Engineer)&lt;/a> — recorrido por dentro del agente.&lt;/li>
&lt;li>&lt;a href="https://medium.com/@mughal.asim/tetragon-series-part-2-enforcing-sensitive-file-access-with-a-namespaced-tracingpolicy-3c2f617ec912">Tetragon Series, Part 2: Enforcing Sensitive File Access (Medium)&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>Ecosistema:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.cilium.io/en/stable/observability/hubble/">Cilium Hubble — observabilidad de red&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://falco.org/">Falco — sitio oficial&lt;/a> — el otro grande del campo.&lt;/li>
&lt;li>&lt;a href="https://kubearmor.io/">KubeArmor&lt;/a> — la tercera opción, con AppArmor + eBPF.&lt;/li>
&lt;/ul>
&lt;p>Cross-references:&lt;/p>
&lt;ul>
&lt;li>Parte 1 de la serie: &lt;a href="https://blog.lo0.es/posts/ebpf-cilium-tcp-ip-bypass/">eBPF de cero a Cilium: cómo el kernel aprendió a saltarse su propia pila TCP/IP&lt;/a> — los fundamentos de eBPF que aquí damos por leídos.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/posts/rke2-cilium-bgp/">Kubernetes con Cilium BGP: servicios accesibles sin Ingress&lt;/a> — punto de partida del ecosistema Cilium en este blog.&lt;/li>
&lt;/ul></description></item><item><title>eBPF de cero a Cilium: cómo el kernel aprendió a saltarse su propia pila TCP/IP</title><link>https://blog.lo0.es/posts/ebpf-cilium-tcp-ip-bypass/</link><pubDate>Tue, 19 May 2026 04:30:00 +0200</pubDate><guid>https://blog.lo0.es/posts/ebpf-cilium-tcp-ip-bypass/</guid><description>&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>eBPF es &lt;strong>una máquina virtual sandboxed dentro del kernel Linux&lt;/strong> que ejecuta código verificado en hooks bien definidos: kprobes, tracepoints, socket events, drivers de red. Antes de eBPF, modificar el comportamiento del kernel era recompilarlo o cargar un módulo arbitrario; con eBPF, cargas un programa pequeño que pasa un verificador formal y se ejecuta a velocidad nativa con seguridad de memoria. En networking, esto se traduce en que &lt;strong>el paquete no tiene que recorrer la pila TCP/IP tradicional&lt;/strong>: un programa eBPF en el driver de la NIC (XDP) puede dropear, reenviar o reescribir el paquete antes de que el kernel haya hecho su primer alloc; un programa en cgroup hooks (sock_ops) puede redirigir conexiones a otro socket sin que el paquete llegue siquiera a salir de la máquina. Cilium es el CNI que ha llevado esto a su conclusión lógica: &lt;strong>reemplaza kube-proxy por eBPF puro&lt;/strong> (O(1) en lugar de O(N) de iptables), enruta pod-a-pod sin VXLAN cuando puede, evalúa Network Policies con BPF maps, y desde 1.16 ha rehecho su control plane de BGP con un set nuevo de CRDs —&lt;code>CiliumBGPClusterConfig&lt;/code>, &lt;code>CiliumBGPPeerConfig&lt;/code>, &lt;code>CiliumBGPAdvertisement&lt;/code>, &lt;code>CiliumBGPNodeConfigOverride&lt;/code>— que sustituyen al monolítico &lt;code>CiliumBGPPeeringPolicy&lt;/code> que ya está deprecado. Este artículo baja por las tres capas (eBPF básico → eBPF networking → Cilium) y termina con los CRDs operativos.&lt;/p>
&lt;h2 id="la-analogía-plugins-firmados-para-el-kernel">La analogía: plugins firmados para el kernel&lt;/h2>
&lt;p>Imagina el navegador. Hace 20 años, extender un navegador significaba compilar un binario nativo y cargarlo: cualquier extensión podía estrellarlo, corromper memoria, leer cookies del banco. Hoy, las extensiones son &lt;strong>JavaScript en una sandbox&lt;/strong> con un manifest que declara permisos, un runtime que aplica el aislamiento y una tienda que firma el código. La extensión no toca el binario del navegador; vive en un mundo controlado y solo puede hablar con el navegador a través de APIs definidas. Resultado: extensibilidad masiva con superficie de ataque acotada.&lt;/p>
&lt;p>eBPF es exactamente eso para el kernel Linux. Cargar un módulo &lt;code>.ko&lt;/code> clásico es cargar código nativo con acceso total a memoria del kernel: un bug y se va el sistema. eBPF es &lt;strong>una VM bytecode&lt;/strong> con verificador estático, allocator controlado, JIT al hardware nativo después de pasar el verificador, y un set de &amp;ldquo;helpers&amp;rdquo; del kernel a los que puede llamar. El programa eBPF puede leer la memoria del kernel donde el verificador le permite leer, y solo eso. No puede entrar en loops infinitos (el verificador exige que termine). No puede saltar a direcciones arbitrarias. No puede dereferenciar punteros sin haberlos validado primero. Y, lo más importante: &lt;strong>es código de usuario, cargado en runtime, que ejecuta dentro del kernel a velocidad nativa&lt;/strong>.&lt;/p>
&lt;p>Las consecuencias se notan a kilómetros. Antes, observar tráfico en producción significaba parchear el kernel o cargar un módulo de riesgo. Hoy, &lt;code>bpftrace -e 'tracepoint:net:net_dev_xmit { @[args-&amp;gt;dev-&amp;gt;name] = count(); }'&lt;/code> te da un histograma de paquetes por interfaz en tres líneas y cero downtime. Antes, sustituir iptables por algo más rápido implicaba reescribir el subsistema de netfilter. Hoy, Cilium carga 60 KB de bytecode eBPF en XDP y desbanca a iptables con un map de hashes.&lt;/p>
&lt;h2 id="ebpf-básico-qué-es-y-qué-no-es">eBPF básico: qué es y qué no es&lt;/h2>
&lt;h3 id="el-origen-y-el-alcance">El origen y el alcance&lt;/h3>
&lt;p>El nombre viene de &lt;strong>Berkeley Packet Filter&lt;/strong>, una idea de 1992 (McCanne y Jacobson) para filtrar paquetes con un mini-bytecode que &lt;code>tcpdump&lt;/code> usaba internamente. En 2014, Alexei Starovoitov lo rebautizó como &lt;strong>eBPF&lt;/strong> y lo extendió enormemente: 11 registros de 64 bits en lugar de 2 de 32, stack de 512 bytes, mapas como estructuras compartidas con userspace, JIT al hardware nativo, y un verificador formal mucho más sofisticado. De ser un filtro de paquetes, pasó a ser &lt;strong>un mecanismo de extensibilidad genérico del kernel&lt;/strong>.&lt;/p>
&lt;p>Hoy eBPF se usa para cuatro cosas:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Networking&lt;/strong>: XDP, TC, cgroup hooks, socket ops, lightweight tunnels.&lt;/li>
&lt;li>&lt;strong>Observabilidad&lt;/strong>: kprobes, uprobes, tracepoints, USDT. La base de proyectos como &lt;code>bpftrace&lt;/code>, &lt;code>bcc&lt;/code>, Pixie, Parca.&lt;/li>
&lt;li>&lt;strong>Seguridad&lt;/strong>: BPF LSM (Linux Security Module en eBPF), bloqueos de syscall con seccomp-bpf. Falco, Tetragon, Tracee.&lt;/li>
&lt;li>&lt;strong>Scheduling&lt;/strong>: sched_ext (kernel 6.12+), schedulers de procesos completamente en eBPF. Aún en fase muy temprana.&lt;/li>
&lt;/ol>
&lt;h3 id="la-vm">La VM&lt;/h3>
&lt;p>Un programa eBPF se compila desde C (o Rust, Go con cilium/ebpf) a bytecode eBPF, no a x86/arm64 directamente. El loader del kernel (vía syscall &lt;code>bpf()&lt;/code>) pasa ese bytecode por &lt;strong>el verificador&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Reconstruye el grafo de control de flujo.&lt;/li>
&lt;li>Hace análisis estático de cada path posible: cada instrucción tiene que ser alcanzable, cada acceso a memoria tiene que estar dentro de bounds conocidos, cada puntero tiene que haber sido validado.&lt;/li>
&lt;li>Rechaza loops sin un upper bound conocido. Los kernels recientes admiten loops acotados (&lt;code>bpf_loop&lt;/code> helper), pero el contador siempre es finito.&lt;/li>
&lt;li>Rechaza llamadas a helpers o kfuncs que el program type del hook no permita.&lt;/li>
&lt;/ul>
&lt;p>Si el verificador acepta el programa, el JIT lo traduce a código nativo del host (x86, arm64, etc.) y queda atado a su hook. A partir de ahí se ejecuta cada vez que el evento del hook ocurre, &lt;strong>sin context switch a userspace&lt;/strong>, &lt;strong>sin coste de syscall&lt;/strong>. Latencias del orden de cientos de nanosegundos por invocación.&lt;/p>
&lt;h3 id="maps-el-puente-con-userspace">Maps: el puente con userspace&lt;/h3>
&lt;p>Un programa eBPF aislado no sirve de mucho. Lo que lo hace útil son los &lt;strong>maps&lt;/strong>: estructuras de datos compartidas entre el programa kernel y el espacio de usuario. Hay varios tipos:&lt;/p>
&lt;ul>
&lt;li>&lt;code>BPF_MAP_TYPE_HASH&lt;/code>, &lt;code>BPF_MAP_TYPE_LRU_HASH&lt;/code>: hash tables con o sin desalojo LRU.&lt;/li>
&lt;li>&lt;code>BPF_MAP_TYPE_ARRAY&lt;/code>, &lt;code>BPF_MAP_TYPE_PERCPU_ARRAY&lt;/code>: arrays, opcionalmente per-CPU para evitar contención.&lt;/li>
&lt;li>&lt;code>BPF_MAP_TYPE_RINGBUF&lt;/code>, &lt;code>BPF_MAP_TYPE_PERF_EVENT_ARRAY&lt;/code>: canales para enviar eventos a userspace en streaming.&lt;/li>
&lt;li>&lt;code>BPF_MAP_TYPE_PROG_ARRAY&lt;/code>: arrays de programas eBPF para tail calls (encadenamiento de programas sin volver al kernel base).&lt;/li>
&lt;/ul>
&lt;p>Userspace lee y escribe estos maps vía syscalls &lt;code>bpf()&lt;/code>; el programa kernel los lee y escribe directamente. Es la base de cualquier sistema eBPF: el programa kernel recoge datos en un map, el daemon en userspace los lee. Cilium hace exactamente esto: el agente userland (Go) gestiona la política y la traduce a entradas en maps; los programas eBPF que viven en XDP/TC leen los maps y aplican las decisiones.&lt;/p>
&lt;h3 id="co-re-compila-una-vez-corre-en-cualquier-kernel">CO-RE: compila una vez, corre en cualquier kernel&lt;/h3>
&lt;p>Una pesadilla clásica de los módulos de kernel: están atados a la versión exacta del kernel donde se compilaron. Distribuir un módulo precompilado para un parque de máquinas con distintas distros era imposible.&lt;/p>
&lt;p>eBPF resuelve esto con &lt;strong>CO-RE (Compile Once, Run Everywhere)&lt;/strong>: el bytecode incluye &lt;strong>relocaciones&lt;/strong> que el loader resuelve en cada kernel concreto consultando &lt;strong>BTF (BPF Type Format)&lt;/strong>, una representación del layout de las structs del kernel que el propio kernel publica. Resultado: un único binario eBPF funciona en kernels 5.10, 5.15, 6.1 y 6.8 sin recompilar, porque el loader ajusta los offsets de acceso a structs en runtime.&lt;/p>
&lt;p>Esto es lo que ha permitido que distribuciones eBPF productivas existan. Sin CO-RE, cada kernel sería un proyecto de portado.&lt;/p>
&lt;h2 id="ebpf-en-networking-los-hooks-que-importan">eBPF en networking: los hooks que importan&lt;/h2>
&lt;p>Dentro del subsistema de red de Linux, eBPF tiene varios hooks. Los relevantes para CNIs:&lt;/p>
&lt;h3 id="xdp--express-data-path">XDP — eXpress Data Path&lt;/h3>
&lt;p>XDP es &lt;strong>el hook más temprano&lt;/strong>: se ejecuta en el driver de la NIC, &lt;strong>antes de que el paquete entre en el kernel propiamente&lt;/strong>. No hay &lt;code>sk_buff&lt;/code> (la struct que el resto del kernel usa para representar paquetes); solo hay un puntero a un buffer de RAM con los bytes recibidos.&lt;/p>
&lt;p>Las acciones que un programa XDP puede devolver:&lt;/p>
&lt;ul>
&lt;li>&lt;code>XDP_DROP&lt;/code>: tirar el paquete inmediatamente. El driver lo deja caer y libera el buffer. Coste: nanosegundos. Caso de uso: DDoS mitigation. Cloudflare procesó &lt;strong>más de 8 millones de paquetes/segundo por CPU&lt;/strong> con XDP para drop de SYN floods.&lt;/li>
&lt;li>&lt;code>XDP_PASS&lt;/code>: dejar que el paquete siga al kernel normal. Pasa a &lt;code>sk_buff&lt;/code> y entra en el stack tradicional.&lt;/li>
&lt;li>&lt;code>XDP_TX&lt;/code>: reenviar por la misma interfaz tras posibles modificaciones. Útil para load balancers L4 que reescriben destino y devuelven.&lt;/li>
&lt;li>&lt;code>XDP_REDIRECT&lt;/code>: enviar el paquete a otra interfaz o a un map (para forward a userspace via AF_XDP, o a otra NIC, o a un veth de un pod).&lt;/li>
&lt;li>&lt;code>XDP_ABORTED&lt;/code>: error (incrementa un contador, dropea).&lt;/li>
&lt;/ul>
&lt;p>Casos de uso reales:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Cloudflare L3 DDoS protection&lt;/strong>: reglas XDP que drop millones de paquetes/s.&lt;/li>
&lt;li>&lt;strong>Facebook Katran&lt;/strong>: L4 load balancer que reescribe destino IP y devuelve por la misma interfaz. Maneja 10× más conexiones por servidor que IPVS clásico.&lt;/li>
&lt;li>&lt;strong>Cilium XDP acceleration&lt;/strong>: load balancing de Services en la capa más baja posible.&lt;/li>
&lt;/ul>
&lt;h3 id="tc-traffic-control--clsact-con-bpf">TC (Traffic Control) — clsact con BPF&lt;/h3>
&lt;p>XDP es muy rápido pero limitado: el paquete aún no tiene &lt;code>sk_buff&lt;/code> y muchas decisiones (conntrack, NAT, encapsulación con metadatos) son más fáciles cuando sí lo tiene. El hook &lt;strong>TC clsact con BPF&lt;/strong> se ejecuta &lt;strong>después&lt;/strong> de construir el &lt;code>sk_buff&lt;/code> pero &lt;strong>antes de&lt;/strong> las decisiones de routing y netfilter. Acciones:&lt;/p>
&lt;ul>
&lt;li>&lt;code>TC_ACT_OK&lt;/code>: el paquete sigue por el stack.&lt;/li>
&lt;li>&lt;code>TC_ACT_SHOT&lt;/code>: drop.&lt;/li>
&lt;li>&lt;code>TC_ACT_REDIRECT&lt;/code>: redirigir a otra interfaz.&lt;/li>
&lt;li>&lt;code>TC_ACT_PIPE&lt;/code>, &lt;code>TC_ACT_STOLEN&lt;/code>: control de pipeline para combinarse con otros qdiscs.&lt;/li>
&lt;/ul>
&lt;p>Casos de uso:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Network policy stateful&lt;/strong>: Cilium evalúa políticas L3-L7 en TC con &lt;code>sk_buff&lt;/code> completo y conntrack disponible.&lt;/li>
&lt;li>&lt;strong>Marcado y QoS&lt;/strong>: marcado de tráfico para que el scheduler aplique prioridades.&lt;/li>
&lt;li>&lt;strong>Encapsulación overlay&lt;/strong>: añadir headers VXLAN/Geneve cuando el modo es tunnel.&lt;/li>
&lt;/ul>
&lt;p>XDP y TC se combinan: &lt;strong>XDP para lo barato y temprano&lt;/strong> (DDoS, LB simple), &lt;strong>TC para lo que necesita &lt;code>skb&lt;/code> y stateful&lt;/strong>.&lt;/p>
&lt;h3 id="cgroup-hooks-sock_ops-y-cgroup_sock_addr">Cgroup hooks: sock_ops y CGROUP_SOCK_ADDR&lt;/h3>
&lt;p>El paso conceptual más radical: hooks que no están en la capa de red sino &lt;strong>en la capa de socket&lt;/strong>. Tipos relevantes:&lt;/p>
&lt;ul>
&lt;li>&lt;code>BPF_PROG_TYPE_CGROUP_SOCK_ADDR&lt;/code>: se invoca cuando un proceso de un cgroup hace &lt;code>connect()&lt;/code>, &lt;code>bind()&lt;/code>, &lt;code>sendto()&lt;/code>. El programa eBPF puede &lt;strong>reescribir la dirección de destino&lt;/strong> antes de que la conexión salga. Es lo que permite a Cilium hacer load balancing de Services &lt;strong>sin que el paquete entre en la pila de red&lt;/strong>: si el cliente intenta conectar a &lt;code>10.96.0.1:443&lt;/code> (ClusterIP), un programa eBPF en este hook reescribe el destino a la IP real del pod backend antes de que el syscall continúe.&lt;/li>
&lt;li>&lt;code>BPF_PROG_TYPE_SOCK_OPS&lt;/code>: se invoca en eventos TCP (creación, establecido, retransmisión). Permite ajustar parámetros del socket en runtime y, lo más importante, &lt;strong>emparejar sockets locales&lt;/strong> vía &lt;code>bpf_sk_assign&lt;/code> para shortcut sin que el paquete viaje por la red.&lt;/li>
&lt;/ul>
&lt;p>Esta es la &amp;ldquo;tercera capa&amp;rdquo; del bypass: no es solo más rápido, es &lt;strong>conceptualmente distinto&lt;/strong>. El paquete no se construye, no se serializa, no recorre IP layer ni TCP layer. Es la diferencia entre acelerar una carretera y descubrir que para algunos viajes no hace falta tomar el coche.&lt;/p>
&lt;h2 id="el-camino-largo-cómo-es-la-pila-tcpip-tradicional">El camino largo: cómo es la pila TCP/IP tradicional&lt;/h2>
&lt;p>Para apreciar lo que eBPF ahorra, vale la pena trazar el recorrido completo de un paquete por la pila Linux. Tomemos el caso &amp;ldquo;paquete entra por una NIC, va a un proceso local&amp;rdquo;:&lt;/p>
&lt;pre tabindex="0">&lt;code>NIC (DMA al ring buffer del driver)
↓
driver: napi_schedule, poll, asigna sk_buff
↓
[XDP hook] ← si hay programa XDP, se decide aquí
↓
netif_receive_skb
↓
__netif_receive_skb_core
↓
[TC ingress clsact + BPF] ← si hay programa TC ingress
↓
packet_type handlers (IP, ARP...)
↓
ip_rcv → ip_rcv_core
↓
[netfilter NF_INET_PRE_ROUTING] ← iptables PREROUTING
↓
routing decision (FIB lookup)
↓
[netfilter NF_INET_LOCAL_IN] o [NF_INET_FORWARD]
↓
tcp_v4_rcv → tcp_v4_do_rcv
↓
tcp_rcv_established
↓
sk_data_ready
↓
proceso lee con recv()/read()
&lt;/code>&lt;/pre>&lt;p>Cada flecha es una llamada de función con coste medible. Cada netfilter hook recorre todas las reglas iptables/nftables registradas. Con kube-proxy en modo iptables y 5 000 Services × 10 endpoints cada uno, hay del orden de &lt;strong>150 000 reglas&lt;/strong> que se evalúan secuencialmente en &lt;code>NF_INET_PRE_ROUTING&lt;/code>. Los benchmarks publicados muestran latencias de &lt;strong>decenas de microsegundos por paquete&lt;/strong> en clusters Kubernetes grandes solo en el paso de netfilter, &lt;strong>antes&lt;/strong> de que la aplicación reciba nada.&lt;/p>
&lt;p>Y eso es el camino normal. En el camino de salida pasa lo mismo pero en sentido inverso: &lt;code>tcp_sendmsg → ip_output → NF_INET_LOCAL_OUT → routing → NF_INET_POSTROUTING → dev_queue_xmit → driver → NIC&lt;/code>.&lt;/p>
&lt;h2 id="cómo-cilium-se-salta-esta-pila">Cómo Cilium se salta esta pila&lt;/h2>
&lt;p>Cilium no elimina la pila TCP/IP; sigue ahí para los casos que la necesitan. Lo que hace es &lt;strong>shortcuts&lt;/strong> en los puntos donde duele.&lt;/p>
&lt;h3 id="shortcut-1--xdp-para-el-datapath-de-service">Shortcut 1 — XDP para el datapath de Service&lt;/h3>
&lt;p>Para un cluster con 5 000 Services, kube-proxy iptables tiene un coste O(N) en evaluar reglas (incluso con &lt;code>iptables-restore --noflush&lt;/code> y trucos, sigue siendo lineal en el número de chains que el paquete atraviesa).&lt;/p>
&lt;p>Cilium lo sustituye así:&lt;/p>
&lt;ul>
&lt;li>Cada Service y sus endpoints viven en &lt;strong>un eBPF hash map&lt;/strong>.&lt;/li>
&lt;li>Cuando entra un paquete con destino a una ClusterIP, el programa XDP de Cilium hace &lt;strong>un lookup O(1)&lt;/strong> en ese map y obtiene el endpoint backend.&lt;/li>
&lt;li>Reescribe el destino y &lt;code>XDP_TX&lt;/code> (devuelve por la misma interfaz hacia el backend) o &lt;code>XDP_REDIRECT&lt;/code> (lo envía a la veth del pod local correspondiente).&lt;/li>
&lt;/ul>
&lt;p>Esto significa que el coste no crece con el número de Services. 100 Services o 100 000, &lt;strong>lookup constante en el map&lt;/strong>. Benchmarks publicados muestran reducciones de latencia de &lt;strong>30-50%&lt;/strong> en clusters con muchos Services frente a kube-proxy iptables, y de orden de magnitud frente a IPVS en algunos casos.&lt;/p>
&lt;h3 id="shortcut-2--socket-lb-el-paquete-no-se-llega-a-construir">Shortcut 2 — socket-LB: el paquete no se llega a construir&lt;/h3>
&lt;p>Cilium 1.6+ introdujo el &lt;strong>socket-level load balancing&lt;/strong>, basado en cgroup hooks. Funciona así:&lt;/p>
&lt;ul>
&lt;li>Cuando un pod hace &lt;code>connect(10.96.0.1:443)&lt;/code> (ClusterIP de un Service), el syscall entra en el kernel.&lt;/li>
&lt;li>Antes de que el kernel construya nada de red, &lt;strong>un programa eBPF en &lt;code>CGROUP_SOCK_ADDR/connect4&lt;/code>&lt;/strong> intercepta y &lt;strong>reescribe la dirección de destino&lt;/strong> a la IP real del pod backend.&lt;/li>
&lt;li>El kernel continúa con el &lt;code>connect&lt;/code> como si el cliente hubiera escrito directamente &lt;code>10.0.0.42:8080&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>¿Por qué importa? Porque cuando el pod backend está &lt;strong>en el mismo nodo&lt;/strong>, este shortcut convierte una llamada que habría implicado:&lt;/p>
&lt;pre tabindex="0">&lt;code>syscall connect → kernel stack → veth → bridge → veth → kernel stack → syscall accept
&lt;/code>&lt;/pre>&lt;p>en:&lt;/p>
&lt;pre tabindex="0">&lt;code>syscall connect (con destino reescrito) → loopback directo
&lt;/code>&lt;/pre>&lt;p>La pila TCP/IP se evita literalmente. No hay paquete encapsulado, no hay viaje por veth pairs, no hay netfilter. Latencias L7 de pod-a-pod en el mismo nodo bajan a niveles de &lt;strong>comunicación local&lt;/strong> (~5-15 µs en lugar de ~30-50 µs para servicios con kube-proxy iptables y veth tradicional).&lt;/p>
&lt;h3 id="shortcut-3--direct-routing-pod-a-pod">Shortcut 3 — direct routing pod-a-pod&lt;/h3>
&lt;p>El modo overlay tradicional (Flannel, Calico VXLAN) encapsula cada paquete pod-a-pod en VXLAN/Geneve. Cada paquete carga un header extra de 50 bytes, requiere encap/decap, y consume MTU.&lt;/p>
&lt;p>Cilium soporta &lt;strong>direct routing&lt;/strong>: los pod CIDRs se anuncian a la fabric subyacente (con BGP, ahí entra el control plane que veremos) y los routers físicos enrutan los paquetes pod-a-pod &lt;strong>sin encapsular&lt;/strong>. El paquete sale de un pod con su IP original como source y la IP del pod destino como dest, la NIC del nodo lo entrega a la red, la red lo enruta, llega al nodo destino y se entrega al pod. Cero encap, MTU completo, latencia mínima.&lt;/p>
&lt;p>Cilium hace esto &lt;strong>vía programas eBPF en TC&lt;/strong> que reescriben las cabeceras necesarias y deciden si el paquete va por encap o direct según la política configurada por nodo.&lt;/p>
&lt;h3 id="shortcut-4--network-policy-en-tc-con-maps">Shortcut 4 — Network Policy en TC con maps&lt;/h3>
&lt;p>Las Network Policies en CNIs clásicos suelen traducirse a reglas iptables, otro factor que explota linealmente. Cilium las evalúa en programas eBPF que leen &lt;strong>maps de identity&lt;/strong>: cada workload tiene un identifier numérico calculado desde sus labels, y la policy es un map &lt;code>(src_identity, dst_identity, port, proto) → allow|deny&lt;/code>. Un lookup en hash map por paquete.&lt;/p>
&lt;p>Esto también permite las &lt;strong>L7 policies&lt;/strong> de Cilium (filtrado HTTP, gRPC, Kafka): el programa eBPF reconoce el handshake L7, redirige selectivamente al proxy Envoy embebido (que vive como sidecar del datapath, no como sidecar de pod) y solo en ese subset paga el coste del proxy L7. Todo el tráfico L3/L4 sigue por el fast path eBPF.&lt;/p>
&lt;h2 id="cilium-la-arquitectura">Cilium: la arquitectura&lt;/h2>
&lt;p>Cilium combina dos planos:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Agent (Go)&lt;/strong>: vive como DaemonSet en cada nodo. Es lo &amp;ldquo;lento&amp;rdquo;: traduce el deseo expresado en CRDs (CiliumNetworkPolicy, CiliumBGPClusterConfig, etc.) en entradas en eBPF maps. Habla con el API server de Kubernetes para descubrir endpoints, services, pods. Embebe un GoBGP para el control plane de BGP. Embebe un Envoy para L7 policies.&lt;/li>
&lt;li>&lt;strong>Datapath (eBPF)&lt;/strong>: los programas cargados en XDP, TC, cgroup hooks. Son lo &amp;ldquo;rápido&amp;rdquo;: ven cada paquete, leen los maps que el agent mantiene, deciden en nanosegundos.&lt;/li>
&lt;/ul>
&lt;p>Esta separación es lo que hace operacionalmente cómodo a Cilium: el deseo se expresa en YAML, el agent lo materializa en maps, los maps son leídos por el datapath. Si el agent se cae temporalmente, el datapath sigue funcionando con la última configuración cargada. Como en cualquier sistema de control/data plane bien hecho.&lt;/p>
&lt;h2 id="el-bgp-control-plane-v2-los-crds-que-tienes-que-conocer">El BGP Control Plane v2: los CRDs que tienes que conocer&lt;/h2>
&lt;p>Cilium ha tenido soporte de BGP varios años. La primera versión usaba un único CRD monolítico, &lt;code>CiliumBGPPeeringPolicy&lt;/code>, que mezclaba en un solo objeto la configuración del nodo, los peers, los timers y los anuncios. Desde &lt;strong>Cilium 1.16&lt;/strong> existe el &lt;strong>BGP Control Plane v2&lt;/strong>, que descompone esa configuración en CRDs separados con responsabilidades claras. El &lt;code>CiliumBGPPeeringPolicy&lt;/code> (API &lt;code>cilium.io/v2alpha1&lt;/code>) está &lt;strong>deprecated&lt;/strong> y los avisos de migración aparecen en los logs del operator si todavía lo usas.&lt;/p>
&lt;p>Los CRDs nuevos (API &lt;code>cilium.io/v2&lt;/code>):&lt;/p>
&lt;h3 id="1-ciliumbgpclusterconfig">1. &lt;code>CiliumBGPClusterConfig&lt;/code>&lt;/h3>
&lt;p>Define &lt;strong>instancias BGP&lt;/strong> y los peers a los que se conectan, desde la perspectiva del cluster. Se selecciona qué nodos aplican esta configuración con un &lt;code>nodeSelector&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CiliumBGPClusterConfig&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium-bgp-cluster&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">nodeSelector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">bgp-policy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rack-1 &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># solo nodos con esta label&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">bgpInstances&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">instance-65000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">localASN&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">65000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">top-of-rack-1a&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerASN&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">64512&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerAddress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.1.1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerConfigRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">tor-shared-config &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># → referencia a CiliumBGPPeerConfig&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">top-of-rack-1b&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerASN&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">64512&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerAddress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.1.2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerConfigRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">tor-shared-config&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Una instancia BGP es la abstracción &amp;ldquo;este nodo participa en BGP con este ASN local y estos peers&amp;rdquo;. Pueden coexistir varias en un mismo nodo (multi-instancia para multi-VRF).&lt;/p>
&lt;h3 id="2-ciliumbgppeerconfig">2. &lt;code>CiliumBGPPeerConfig&lt;/code>&lt;/h3>
&lt;p>Define los &lt;strong>parámetros compartidos&lt;/strong> del peering: timers, address families, transport, password MD5, graceful restart, etc. Se referencia desde &lt;code>CiliumBGPClusterConfig&lt;/code> via &lt;code>peerConfigRef&lt;/code>. Esto evita repetir la misma configuración para cada peer cuando hay decenas de ellos.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CiliumBGPPeerConfig&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">tor-shared-config&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">timers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">holdTimeSeconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">30&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">keepAliveTimeSeconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">connectRetryTimeSeconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">5&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">gracefulRestart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restartTimeSeconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">120&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">families&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">afi&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ipv4&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">safi&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unicast&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">advertisements&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">advertise&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">bgp &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># → liga a CiliumBGPAdvertisement&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">afi&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ipv6&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">safi&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unicast&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">advertisements&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">advertise&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">bgp&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">authentication&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">password&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">bgp-md5-secret &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Secret con la password MD5&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">key&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">password&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Una sola &lt;code>CiliumBGPPeerConfig&lt;/code> puede ser referenciada por &lt;strong>muchos peers&lt;/strong> distintos. Cambias timers o families en un sitio.&lt;/p>
&lt;h3 id="3-ciliumbgpadvertisement">3. &lt;code>CiliumBGPAdvertisement&lt;/code>&lt;/h3>
&lt;p>Declara &lt;strong>qué prefijos se anuncian&lt;/strong>: los pod CIDRs del nodo, los ClusterIPs y ExternalIPs de Services, las IPs asignadas por &lt;code>CiliumLoadBalancerIPPool&lt;/code> para Services type=LoadBalancer. Se vinculan a &lt;code>CiliumBGPPeerConfig&lt;/code> via labels.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CiliumBGPAdvertisement&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">services-and-pods&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">advertise&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">bgp &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># ← la label que el PeerConfig matchea&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">advertisements&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">advertisementType&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">PodCIDR &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># anuncia el pod CIDR del nodo&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">attributes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">communities&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">standard&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;65000:100&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">advertisementType&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Service &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># anuncia ClusterIPs / LoadBalancer IPs&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">service&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">addresses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">LoadBalancerIP&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">ClusterIP&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">ExternalIP&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">bgp-advertise&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;true&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># solo Services con esta label&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">attributes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">communities&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">standard&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;65000:200&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">localPreference&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">200&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>La granularidad es muy fina: puedes anunciar diferentes tipos de prefijos con diferentes communities BGP, diferentes local-preference, diferentes path attributes, y filtrar Services con label selectors. Esto era literalmente imposible con &lt;code>CiliumBGPPeeringPolicy&lt;/code> v1.&lt;/p>
&lt;h3 id="4-ciliumbgpnodeconfig-auto-generado">4. &lt;code>CiliumBGPNodeConfig&lt;/code> (auto-generado)&lt;/h3>
&lt;p>Este CRD no se configura a mano. El &lt;strong>operator de Cilium&lt;/strong> lo genera por cada nodo a partir de la &lt;code>CiliumBGPClusterConfig&lt;/code> que aplica a ese nodo. Es el estado materializado per-node que el agente de cada nodo lee para arrancar sus peerings. Si quieres ver qué configuración BGP está corriendo realmente en un nodo, &lt;code>kubectl get ciliumbgpnodeconfig &amp;lt;nodename&amp;gt; -o yaml&lt;/code> te lo enseña.&lt;/p>
&lt;h3 id="5-ciliumbgpnodeconfigoverride">5. &lt;code>CiliumBGPNodeConfigOverride&lt;/code>&lt;/h3>
&lt;p>Opcional. Permite &lt;strong>sobrescribir la configuración generada&lt;/strong> para un nodo concreto cuando necesitas algo no-estándar. Casos de uso:&lt;/p>
&lt;ul>
&lt;li>Anclar el router-id BGP a una IP específica (útil cuando el nodo tiene varias interfaces).&lt;/li>
&lt;li>Especificar la dirección local del peer cuando hay varias interfaces de salida.&lt;/li>
&lt;li>Cambiar timers solo para un nodo problemático.&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CiliumBGPNodeConfigOverride&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">node-rack1-master01 &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># nombre debe coincidir con el del nodo&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">bgpInstances&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">instance-65000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">routerID&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.1.10&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># override del router-id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">top-of-rack-1a&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">localAddress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.1.10&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># interface local concreta&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="diagrama-de-relaciones">Diagrama de relaciones&lt;/h3>
&lt;div class="diagram" style="max-width:720px;margin:1.5rem auto;">
&lt;svg viewBox="0 0 720 320" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Diagrama de relaciones entre CRDs de Cilium BGP v2">
&lt;style>.title{font:600 13px sans-serif;fill:#222}.lbl{font:600 12px sans-serif;fill:#222}.sm{font:11px sans-serif;fill:#555}.box{stroke:#444;stroke-width:1.4}.c1{fill:#ffe9d6}.c2{fill:#d6eaff}.c3{fill:#d9f5d6}.c4{fill:#e9d6f5}.c5{fill:#eee;stroke-dasharray:4 2}.arr{stroke:#666;stroke-width:1.4;fill:none;marker-end:url(#h)}.dashed{stroke:#888;stroke-width:1.2;fill:none;stroke-dasharray:4 3;marker-end:url(#h)}&lt;/style>
&lt;defs>&lt;marker id="h" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">&lt;path d="M0,0 L10,5 L0,10 z" fill="#666"/>&lt;/marker>&lt;/defs>
&lt;text x="360" y="22" text-anchor="middle" class="title">CRDs de Cilium BGP Control Plane v2 y sus relaciones&lt;/text>
&lt;rect x="40" y="50" width="220" height="60" rx="6" class="box c1"/>
&lt;text x="150" y="74" text-anchor="middle" class="lbl">CiliumBGPClusterConfig&lt;/text>
&lt;text x="150" y="94" text-anchor="middle" class="sm">nodeSelector + bgpInstances&lt;/text>
&lt;rect x="290" y="50" width="180" height="60" rx="6" class="box c2"/>
&lt;text x="380" y="74" text-anchor="middle" class="lbl">CiliumBGPPeerConfig&lt;/text>
&lt;text x="380" y="94" text-anchor="middle" class="sm">timers, families, auth&lt;/text>
&lt;rect x="500" y="50" width="180" height="60" rx="6" class="box c3"/>
&lt;text x="590" y="74" text-anchor="middle" class="lbl">CiliumBGPAdvertisement&lt;/text>
&lt;text x="590" y="94" text-anchor="middle" class="sm">pod CIDR, Service IPs&lt;/text>
&lt;rect x="40" y="180" width="220" height="60" rx="6" class="box c5"/>
&lt;text x="150" y="204" text-anchor="middle" class="lbl">CiliumBGPNodeConfig&lt;/text>
&lt;text x="150" y="224" text-anchor="middle" class="sm">auto-generado por operator&lt;/text>
&lt;rect x="290" y="180" width="220" height="60" rx="6" class="box c4"/>
&lt;text x="400" y="204" text-anchor="middle" class="lbl">CiliumBGPNodeConfigOverride&lt;/text>
&lt;text x="400" y="224" text-anchor="middle" class="sm">opcional, por nombre de nodo&lt;/text>
&lt;path class="arr" d="M260,80 L290,80"/>&lt;text x="275" y="74" text-anchor="middle" class="sm">peerConfigRef&lt;/text>
&lt;path class="dashed" d="M380,110 L380,150 L470,180"/>&lt;text x="425" y="155" text-anchor="middle" class="sm">vincula via labels&lt;/text>
&lt;path class="arr" d="M590,110 L590,150 L500,180"/>&lt;text x="545" y="155" text-anchor="middle" class="sm">advertisements&lt;/text>
&lt;path class="arr" d="M150,110 L150,180"/>&lt;text x="165" y="150" text-anchor="middle" class="sm">operator&lt;/text>
&lt;path class="dashed" d="M290,210 L260,210"/>&lt;text x="275" y="205" text-anchor="middle" class="sm">override&lt;/text>
&lt;text x="360" y="290" text-anchor="middle" class="sm">flechas sólidas: referencias YAML directas. Discontinuas: vínculos por label selector o coordinación lateral.&lt;/text>
&lt;/svg>
&lt;/div>
&lt;h3 id="ciliumloadbalancerippool-complementa-no-es-bgp">CiliumLoadBalancerIPPool: complementa, no es BGP&lt;/h3>
&lt;p>Aunque no es un CRD BGP estrictamente, conviene mencionarlo: &lt;strong>&lt;code>CiliumLoadBalancerIPPool&lt;/code>&lt;/strong> es el CRD que provee IPs a Services type=LoadBalancer. Define un rango (&lt;code>10.20.0.0/24&lt;/code>, por ejemplo) que Cilium asigna automáticamente a Services LoadBalancer. Combinado con &lt;code>CiliumBGPAdvertisement&lt;/code> que anuncia &lt;code>LoadBalancerIP&lt;/code>, da el ciclo completo: Service nuevo → IP asignada del pool → anuncio BGP a los routers → IP routable desde la red corporativa, sin balanceador externo.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v2alpha1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CiliumLoadBalancerIPPool&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">lb-pool-rack1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">blocks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">start&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;10.20.0.10&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">stop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;10.20.0.250&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">serviceSelector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">lb-pool&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rack1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="manifest-completo-pod-cidrs--loadbalancer-services-anunciados-a-un-par-tor-redundante">Manifest completo: pod CIDRs + LoadBalancer Services anunciados a un par ToR redundante&lt;/h2>
&lt;p>Ejemplo realista de un cluster con dos top-of-rack switches como peers BGP, ambos en el mismo AS (64512), Cilium en AS 65000:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 1. CiliumBGPPeerConfig — config compartida para los dos ToR&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CiliumBGPPeerConfig&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">tor-peers&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">timers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">holdTimeSeconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">30&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">keepAliveTimeSeconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">gracefulRestart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restartTimeSeconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">120&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">families&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">afi&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ipv4&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">safi&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unicast&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">advertisements&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">advertise&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">bgp&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># 2. CiliumBGPAdvertisement — qué se anuncia&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CiliumBGPAdvertisement&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">pods-and-lb&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">advertise&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">bgp&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">advertisements&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">advertisementType&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">PodCIDR&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">advertisementType&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Service&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">service&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">addresses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="l">LoadBalancerIP]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">selector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchExpressions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- {&lt;span class="w"> &lt;/span>&lt;span class="nt">key: io.kubernetes.service.namespace, operator: NotIn, values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="l">kube-system] }&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># 3. CiliumBGPClusterConfig — qué nodos hablan con qué peers&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CiliumBGPClusterConfig&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cluster-bgp&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">nodeSelector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">bgp&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">enabled&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">bgpInstances&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">instance-65000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">localASN&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">65000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">tor-a&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerASN&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">64512&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerAddress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.1.1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerConfigRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">tor-peers }&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">tor-b&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerASN&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">64512&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerAddress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.1.2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">peerConfigRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">tor-peers }&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># 4. CiliumLoadBalancerIPPool — rango de LB IPs&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cilium.io/v2alpha1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">CiliumLoadBalancerIPPool&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">lb-corporate&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">blocks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">cidr&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;10.20.0.0/24&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Cuatro objetos. Antes, en v1, era un único &lt;code>CiliumBGPPeeringPolicy&lt;/code> que mezclaba todo y resultaba difícil de mantener en clusters de más de 5 nodos con configuración heterogénea. La nueva separación es más larga pero claramente factorizable: un &lt;code>PeerConfig&lt;/code> por tipo de peer, una &lt;code>Advertisement&lt;/code> por política de anuncio, un &lt;code>ClusterConfig&lt;/code> que conecta nodos con peers.&lt;/p>
&lt;h2 id="trampas-operativas-comunes">Trampas operativas comunes&lt;/h2>
&lt;h3 id="modo-routingmode-tunnel-con-bgp">Modo &lt;code>routingMode: tunnel&lt;/code> con BGP&lt;/h3>
&lt;p>BGP solo tiene sentido con &lt;strong>direct routing&lt;/strong> (&lt;code>routingMode: native&lt;/code>). Si tienes el modo tunnel (VXLAN/Geneve) y configuras BGP, anunciarás pod CIDRs pero los paquetes seguirán saliendo encapsulados, generando un comportamiento confuso (a veces vía túnel, a veces directo según rutas). Configura &lt;code>routingMode: native&lt;/code> y desactiva túnel.&lt;/p>
&lt;h3 id="ebpf-host-routing-vs-kube-proxy-replacement">eBPF host routing vs &lt;code>kube-proxy replacement&lt;/code>&lt;/h3>
&lt;p>Son dos cosas distintas. &lt;code>kubeProxyReplacement: true&lt;/code> habilita el reemplazo de kube-proxy (los Services). &lt;code>bpf.hostRouting: true&lt;/code> habilita el bypass de iptables del host (las decisiones de routing del nodo se hacen con eBPF en lugar de FIB tradicional). El segundo necesita kernel 5.10+ con todas las features bpf habilitadas; si no tienes ese kernel, queda en modo legacy y el rendimiento es solo &amp;ldquo;casi tan bueno&amp;rdquo;.&lt;/p>
&lt;h3 id="bgp-timers-agresivos-sobre-nics-flapping">BGP timers agresivos sobre NICs flapping&lt;/h3>
&lt;p>Con &lt;code>holdTimeSeconds: 9 / keepAliveSeconds: 3&lt;/code>, una NIC que parpadee 5 segundos rompe la sesión BGP y todas las rutas anunciadas desaparecen del fabric. Los pods de ese nodo se vuelven inalcanzables hasta que la sesión se restablece. Para clusters en hardware con NICs sospechosas, usa los valores conservadores (&lt;code>holdTime: 30, keepAlive: 10&lt;/code>) y considera &lt;strong>graceful restart&lt;/strong> explícitamente (ya viene en el ejemplo de arriba).&lt;/p>
&lt;h3 id="anunciar-clusterip-a-la-red-corporativa">Anunciar ClusterIP a la red corporativa&lt;/h3>
&lt;p>Anunciar &lt;code>ClusterIP&lt;/code> a routers externos es &lt;strong>rara vez lo que quieres&lt;/strong>: son IPs de Service interno, no diseñadas para alcanzarse desde fuera del cluster. Para exposición externa, usa &lt;code>LoadBalancerIP&lt;/code> desde un &lt;code>CiliumLoadBalancerIPPool&lt;/code>. Anunciar &lt;code>ClusterIP&lt;/code> solo tiene sentido en topologías muy específicas (multi-cluster mesh con shared service discovery).&lt;/p>
&lt;h3 id="mezclar-v2alpha1-ciliumbgppeeringpolicy-y-v2-ciliumbgpclusterconfig">Mezclar v2alpha1 (&lt;code>CiliumBGPPeeringPolicy&lt;/code>) y v2 (&lt;code>CiliumBGPClusterConfig&lt;/code>)&lt;/h3>
&lt;p>No funciona bien. El operator emite warnings en los logs sobre el uso de la API deprecated, y los conflictos entre lo que define la peering policy vs la cluster config pueden producir estados raros. Migra de una a la otra en una sola pasada; no convivas.&lt;/p>
&lt;h3 id="md5-password-y-mtu">MD5 password y MTU&lt;/h3>
&lt;p>Si configuras MD5 password en &lt;code>CiliumBGPPeerConfig.authentication&lt;/code>, el header TCP es más grande. En links con MTU justa (1500 - 50 VXLAN del fabric upstream, por ejemplo), el handshake BGP puede fragmentar y morir silenciosamente. O usa MTU 9000 entre nodos y ToR, o asegura que los MSS están negociados correctamente.&lt;/p>
&lt;h2 id="lo-que-no-hemos-cubierto">Lo que no hemos cubierto&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Cilium Cluster Mesh&lt;/strong>: federación de varios clusters Cilium para que sus Services se vean entre sí. Encaja con BGP cuando se quiere routing nativo entre clusters; tiene CRDs propios.&lt;/li>
&lt;li>&lt;strong>L7 Policies y Envoy embebido&lt;/strong>: política HTTP/gRPC/Kafka. Otra capa de eBPF + proxy que merece artículo propio.&lt;/li>
&lt;li>&lt;strong>Hubble&lt;/strong>: observabilidad de tráfico basada en eBPF que Cilium expone. Dashboards de flow logs con cero impacto en latencia.&lt;/li>
&lt;li>&lt;strong>Wireguard transparente&lt;/strong>: encryption pod-a-pod sin sidecars, controlado por Cilium via eBPF redirect a un dataplane WireGuard del kernel.&lt;/li>
&lt;li>&lt;strong>Gateway API en Cilium&lt;/strong>: el sucesor de Ingress, con soporte de primera clase desde Cilium 1.16+.&lt;/li>
&lt;li>&lt;strong>eBPF para LLM serving&lt;/strong>: la conexión natural con la serie anterior de inferencia. Hay trabajos recientes que usan eBPF para fairness multi-tenant en GPUs y para tracking de tokens; territorio de papers, aún no production.&lt;/li>
&lt;/ul>
&lt;p>Es decir, queda material para otros tres artículos de la serie de hoy. Vamos en orden.&lt;/p>
&lt;h2 id="referencias">Referencias&lt;/h2>
&lt;p>Conceptuales y de proyecto:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://ebpf.io/">eBPF.io&lt;/a> — documentación canónica del ecosistema eBPF.&lt;/li>
&lt;li>&lt;a href="https://github.com/iovisor/bcc">The BPF Compiler Collection (bcc)&lt;/a> y &lt;a href="https://github.com/bpftrace/bpftrace">bpftrace&lt;/a> — herramientas para empezar.&lt;/li>
&lt;li>&lt;a href="https://www.programming-helper.com/tech/ebpf-2026-extended-berkeley-packet-filter-observability-security">eBPF en 2026: How Extended Berkeley Packet Filter Became the Engine of Linux Observability and Networking&lt;/a> — estado del arte.&lt;/li>
&lt;/ul>
&lt;p>XDP, TC y firewalling:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/10/html/configuring_firewalls_and_packet_filters/getting-started-with-xdp-and-ebpf">Getting started with XDP and eBPF (Red Hat docs)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://medium.com/@majidbasharat21/full-guide-to-bpf-firewalls-xdp-tc-and-ebpf-integration-81951f19354b">Full Guide to BPF Firewalls: XDP, tc, and eBPF Integration (Medium, 2025)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://blog.cloudflare.com/xdp-on-bpf-and-bonding/">Cloudflare blog: XDP for DDoS mitigation&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://github.com/facebookincubator/katran">Facebook Katran (GitHub)&lt;/a> — L4 LB con XDP, código y paper.&lt;/li>
&lt;/ul>
&lt;p>Cilium:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.cilium.io/">Cilium documentation&lt;/a> — siempre el primer puerto.&lt;/li>
&lt;li>&lt;a href="https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/">Kubernetes Without kube-proxy&lt;/a> — la guía oficial del replacement.&lt;/li>
&lt;li>&lt;a href="https://docs.cilium.io/en/stable/network/bgp-control-plane/bgp-control-plane-configuration/">Cilium BGP Control Plane Resources (docs)&lt;/a> — referencia de los CRDs v2.&lt;/li>
&lt;li>&lt;a href="https://oneuptime.com/blog/post/2026-03-13-cilium-bgp-control-plane-configuration/view">Configuring Cilium BGP Control Plane (OneUptime blog, mar 2026)&lt;/a> — walkthrough.&lt;/li>
&lt;li>&lt;a href="https://sigridjin.medium.com/a-guide-to-bgp-control-plane-and-cluster-mesh-in-cilium-networking-f20dbf64c5ed">A Guide to BGP Control Plane and Cluster Mesh in Cilium Networking (Sigrid Jin, Medium)&lt;/a> — artículo más profundo con casos de uso.&lt;/li>
&lt;/ul>
&lt;p>Cross-references:&lt;/p>
&lt;ul>
&lt;li>Artículo previo en este blog: &lt;a href="https://blog.lo0.es/posts/rke2-cilium-bgp/">Kubernetes con Cilium BGP: servicios accesibles sin Ingress&lt;/a> — el primer paso, con la versión v1 (que ya hay que migrar).&lt;/li>
&lt;li>Series sobre inferencia LLM: &lt;a href="https://blog.lo0.es/posts/kv-cache-fundamentos/">KV cache&lt;/a>, &lt;a href="https://blog.lo0.es/posts/vllm-kubernetes/">vLLM en Kubernetes&lt;/a>, &lt;a href="https://blog.lo0.es/posts/pagedattention-deep-dive/">PagedAttention deep dive&lt;/a>, &lt;a href="https://blog.lo0.es/posts/operators-llm-kubernetes/">Operators LLM K8s&lt;/a> — donde la red rápida (que veremos en los siguientes posts de esta serie) determina el rendimiento real.&lt;/li>
&lt;/ul></description></item><item><title>Kubernetes con Cilium BGP: servicios accesibles sin Ingress</title><link>https://blog.lo0.es/posts/rke2-cilium-bgp/</link><pubDate>Sun, 08 Mar 2026 00:00:00 +0000</pubDate><guid>https://blog.lo0.es/posts/rke2-cilium-bgp/</guid><description>&lt;p>Una de las ventajas de usar Cilium como CNI en Kubernetes es su soporte nativo de BGP. Esto permite anunciar los ClusterIPs y LoadBalancer IPs directamente al router de la LAN, haciendo los servicios accesibles sin necesidad de Ingress o NodePort.&lt;/p>
&lt;h2 id="el-problema">El problema&lt;/h2>
&lt;p>En un clúster Kubernetes estándar, los pods y servicios viven en redes internas no alcanzables desde fuera del clúster. Para acceder a ellos se necesitan NodePort, Ingress o un LoadBalancer externo.&lt;/p>
&lt;p>Con Cilium BGP, los pod CIDRs y service CIDRs se anuncian vía BGP al router upstream, haciendo toda la red del clúster routable desde la LAN.&lt;/p>
&lt;p>&lt;em>Artículo en desarrollo — próximamente con configuraciones completas para RKE2 + CRS327.&lt;/em>&lt;/p></description></item></channel></rss>