Skip to content

Parte 11: BGP Control Plane, IP de balanceadores de carga y salida ​

Base de revisión: Cilium 1.20.2 (estable, 2026-09-16); Cilium CLI 0.20.1; Hubble CLI 1.20.2. Los elementos marcados [versión preliminar 1.21] proceden de v1.21.0-pre.3 y pueden cambiar antes de la disponibilidad general. Última actualización: 15 de octubre de 2026

Este capítulo cubre todo lo que conecta un clúster de Cilium con la red fuera de la red de Pods: anunciar rutas con BGP Control Plane, asignar y anunciar IP de LoadBalancer (LB IPAM, anuncios L2 y Node IPAM), dirigir el tráfico saliente (Egress Gateway), interceptar tráfico dirigido a backends locales al nodo (Local Redirect Policy), preferir backends cercanos (distribución del tráfico) y los puntos de entrada de capa 7 (Ingress y Gateway API). Termina con dos topologías de referencia: switches ToR locales con BGP y EKS detrás de CloudFront.

Capítulos relacionados: análisis detallado de IPAM (Pod IPAM decide qué puede anunciar BGP), enrutamiento superpuesto y nativo, detalles internos del plano de datos eBPF (el reemplazo de kube-proxy en que se basa el balanceo de Services de abajo) y ClusterMesh y actualización.

1. Cómo encaja el tráfico norte-sur ​

A menudo se confunden tres tareas distintas bajo el término «balanceador de carga»:

TareaPregunta que respondeComponente de Cilium
Asignación de direcciones¿Qué IP recibe este Service?LB IPAM (CiliumLoadBalancerIPPool), Node IPAM o un controlador de nube
Alcance¿Cómo aprende la red externa que esa IP está en estos nodos?BGP Control Plane, anuncios L2 o balanceador de carga de nube
Balanceo de cargaCuando un paquete llega a un nodo, ¿qué Pod backend lo recibe?Balanceo de Services de eBPF (reemplazo de kube-proxy) y Envoy para capa 7

Por tanto, BGP Control Plane, los anuncios L2 y LB IPAM son funciones independientes que se combinan. Una combinación habitual en entornos locales es LB IPAM (asigna la VIP) + BGP Control Plane (la anuncia) + reemplazo eBPF de kube-proxy (distribuye el tráfico). loadBalancerClass del Service determina qué función lo administra (sección 6).

Lo que BGP no hace. BGP Control Plane solo anuncia rutas. No programa el plano de datos local y no instala en el kernel ni en los mapas eBPF las rutas aprendidas de los peers. No puede crear conectividad dentro del clúster (descripción general upstream). El enrutamiento Pod a Pod entre nodos corresponde al enrutamiento superpuesto o nativo (parte 9).

2. BGP Control Plane v2 ​

Madurez: v2 (CRD cilium.io/v2) es la única versión de BGP Control Plane en 1.19, 1.20 y la versión preliminar 1.21. CiliumBGPPeeringPolicy de v1 se eliminó en 1.19 (sección 2.9).

2.1 Arquitectura ​

                     user-authored (cluster-scoped, cilium.io/v2)
   +--------------------+   +-------------------+   +----------------------+
   | CiliumBGPCluster   |-->| CiliumBGPPeer     |   | CiliumBGPAdvertise-  |
   | Config             |   | Config            |<--| ment (matched by     |
   |  nodeSelector      |   |  timers, GR, MD5, |   |  LABEL from PeerCfg) |
   |  bgpInstances[]    |   |  families[]       |   +----------------------+
   |  peers[] -> ref    |   +-------------------+
   +---------+----------+
             | watched by cilium-operator
             v
   +--------------------+   (one per selected node, name == node name,
   | CiliumBGPNodeConfig|    read-only for users; status reports sessions)
   +---------+----------+   +--------------------------+
             | watched by   | CiliumBGPNodeConfig-     |  optional per-node
             | the node's   | Override (name == node)  |  routerID/ASN/source
             v agent        +--------------------------+
   +--------------------------------------------+
   | cilium-agent: BGP "router manager"         |
   |   one embedded GoBGP instance per bgpInstance
   |   inputs: NodeConfig, PeerConfig, Advert., |
   |   Secret, Services/EndpointSlices/backends,|
   |   CiliumNode PodCIDRs / CiliumPodIPPool    |
   +----------------------+---------------------+
                          | TCP/179 (agent dials out; active-only by default)
                          v
                    ToR / upstream router

Flujo de control (según pkg/bgp/README.md): el operador observa CiliumBGPClusterConfig y los objetos CiliumBGPPeerConfig / CiliumBGPAdvertisement a los que hace referencia, y crea, actualiza o elimina un CiliumBGPNodeConfig por cada nodo que coincide con nodeSelector de la configuración del clúster. Cada agente observa solo su propio CiliumBGPNodeConfig, además de las configuraciones de peers y anuncios, Secrets, Services y (con varios pools) CiliumPodIPPool, y reconcilia sus instancias de GoBGP. Por eso el operador debe estar ejecutándose para que se propaguen los cambios de configuración.

El speaker es GoBGP integrado en el agente. GoBGP es la única implementación de enrutador compatible. La biblioteca integrada pasó de gobgp/v3 (1.19) a gobgp/v4 (1.20.2 y 1.21.0-pre.3; consulta go.mod de cada etiqueta). Se admiten IPv4 e IPv6, de pila simple y doble, pero solo se pueden anunciar las familias de direcciones que el propio agente use.

2.2 Habilitación ​

yaml
bgpControlPlane:
  enabled: true              # default false
  statusReport:
    enabled: true            # default true; disable on very large clusters to cut API load
  routerIDAllocation:
    mode: default            # default | ip-pool
bash
helm upgrade cilium cilium/cilium -n kube-system --reuse-values \
  --set bgpControlPlane.enabled=true
kubectl -n kube-system rollout restart ds/cilium deploy/cilium-operator
Valor de HelmIndicador del agente/operadorValor predeterminadoDescripción
bgpControlPlane.enabled--enable-bgp-control-planefalseHabilita la función
bgpControlPlane.secretsNamespace.name / .create--bgp-secrets-namespacekube-system / falseNamespace desde el que se leen los Secrets de authSecretRef; el chart puede crearlo
bgpControlPlane.statusReport.enabled--enable-bgp-control-plane-status-reporttrueEscribe el estado de sesión en CiliumBGPNodeConfig.status; al deshabilitarlo se borra el estado
bgpControlPlane.routerIDAllocation.mode / .ipPool--bgp-router-id-allocation-mode / -ip-pooldefault / vacíoEstrategia de Router ID (sección 2.7)
bgpControlPlane.legacyOriginAttribute.enabled--enable-bgp-legacy-origin-attributefalseLas rutas LoadBalancerIP llevan ORIGIN INCOMPLETE (compatible con MetalLB) en vez de IGP
enableNoServiceEndpointsRoutable--enable-no-service-endpoints-routabletrueDetermina si se sigue anunciando una VIP con política Cluster cuando no tiene backends (sección 2.5)

Los valores bgpControlPlane.* son idénticos en 1.18.14, 1.19.8, 1.20.2 y 1.21.0-pre.3 (comparación con values.yaml de cada etiqueta). [Versión preliminar 1.21] los indicadores BGP se trasladaron al módulo pkg/bgp/config, por lo que ahora también aparecen en el conjunto de indicadores del operador (incluidos los de Router ID); el uso de Helm no cambia.

Escuchar en TCP/179 es opcional. De forma predeterminada, bgpInstance no tiene localPort, por lo que el agente solo funciona en modo activo e inicia conexiones a los peers. Si configuras localPort: 179, el agente necesita CAP_NET_BIND_SERVICE en la lista securityContext.capabilities.ciliumAgent del chart; con un puerto alto no se necesita esa capacidad.

2.3 Las cinco CRD ​

Todas tienen ámbito de clúster y usan cilium.io/v2. Las copias cilium.io/v2alpha1 de los mismos tipos están obsoletas (aún se sirven en 1.20.2 y 1.21.0-pre.3 con +kubebuilder:deprecatedversion); escribe todos los manifiestos nuevos con cilium.io/v2.

TipoNombre abreviadoLo escribePropósito
CiliumBGPClusterConfigcbgpclusterusuarioDefine qué nodos ejecutan qué instancias y peers BGP
CiliumBGPPeerConfigcbgppeerusuarioParámetros de sesión y anuncios que se envían a un peer
CiliumBGPAdvertisementcbgpadvertusuarioQué anunciar y con qué atributos
CiliumBGPNodeConfigcbgpnodeoperador (solo lectura para usuarios)Configuración resuelta por nodo y estado de las sesiones
CiliumBGPNodeConfigOverridecbgpnodeoverrideusuarioRouter ID, ASN, puertos y dirección de origen por nodo

Los recursos se vinculan de dos maneras distintas, lo que suele causar errores:

CiliumBGPClusterConfig.spec.bgpInstances[].peers[].peerConfigRef.name  --by NAME-->  CiliumBGPPeerConfig
CiliumBGPPeerConfig.spec.families[].advertisements (label selector)    --by LABELS-> CiliumBGPAdvertisement.metadata.labels

La configuración de peer selecciona anuncios al comparar las etiquetas del objeto CiliumBGPAdvertisement, no sus campos spec. Varios objetos de anuncio pueden coincidir con un peer. Si no coincide ninguno, la sesión se establece, pero no se anuncia ninguna ruta.

CiliumBGPClusterConfig ​

CampoTipo / límitesNotas
spec.nodeSelectorLabelSelectorSi es nulo o está vacío, selecciona todos los nodos. Cada nodo puede coincidir con una sola CiliumBGPClusterConfig
spec.bgpInstances[]De 1 a 16 entradas; clave nameUna instancia de GoBGP por entrada
.nameDe 1 a 255 caracteres, únicoSe referencia desde las anulaciones y aparece en métricas como instance_name
.localASNDe 1 a 4294967295Opcional aquí; una anulación puede definirlo por nodo
.localPortDe 1 a 65535Si no se define, la instancia no escucha
.peers[]clave name
.peers[].peerAddressIPv4 o IPv6Solo es opcional cuando se configura autoDiscovery
.peers[].peerASNDe 0 a 4294967295; predeterminado 00 omite la validación del ASN en el mensaje OPEN del peer
.peers[].autoDiscoverymode: DefaultGateway, defaultGateway.addressFamily: ipv4|ipv6El peer es la puerta de enlace predeterminada del nodo (consulta abajo)
.peers[].peerConfigRef.namecadenaEn cilium.io/v2 solo existe name; group / kind solo están en la CRD obsoleta v2alpha1

Condiciones de estado de la configuración del clúster: cilium.io/NoMatchingNode, cilium.io/MissingPeerConfigs y cilium.io/ConflictingClusterConfig (si dos configuraciones seleccionan el mismo nodo, el operador rechaza la que se procesa después).

Detección automática (DefaultGateway). El agente establece una sesión con la puerta de enlace predeterminada del nodo en lugar de usar un peerAddress fijo. El ToR debe aceptar peers dinámicos (bgp listen range en FRR) y usar el mismo ASN local en todos los ToR. No se admite una puerta de enlace predeterminada de enlace local. Si hay varias rutas predeterminadas (multihoming), Cilium establece una sesión por familia de direcciones, a través de la ruta con la métrica más baja, y cambia a la otra si falla; no puede mantener dos sesiones de esta manera para la misma familia. Para usar dos sesiones, define entradas estáticas peerAddress.

CiliumBGPPeerConfig ​

CampoValor predeterminado / límitesNotas
spec.transport.peerPort179 (de 1 a 65535)Puerto remoto
spec.transport.sourceInterfaceningunoIP de origen tomada de esta interfaz. Debe tener como máximo una dirección apta por familia (no loopback, multicast ni IPv6 de enlace local). Si falta la interfaz, Cilium detecta automáticamente la interfaz de salida. No aparece en la documentación de 1.18; sí desde 1.19
spec.timers.connectRetryTimeSeconds120 (mínimo 1)Con fluctuación: el intervalo efectivo de reintento es [N, 2N)
spec.timers.holdTimeSeconds90 (de 3 a 65535)Cambiar el hold o keepalive reinicia la sesión
spec.timers.keepAliveTimeSeconds30 (de 1 a 65535)Regla de la CRD: keepalive <= holdTime
spec.authSecretRefningunoNombre de un Secret en el namespace de Secrets BGP; clave password (TCP MD5 según RFC 2385)
spec.gracefulRestart.enabledobligatorio si se incluye el bloque
spec.gracefulRestart.restartTimeSeconds120 (de 1 a 4095)
spec.ebgpMultihop1 (de 1 a 255)TTL predeterminado 1; no se aplica a iBGP
spec.families[]selector afi + safi + advertisementsSolo se admiten ipv4/unicast y ipv6/unicast. Si se omite families, se negocian ambas familias unicast, sin anuncios

Condición de estado: cilium.io/MissingAuthSecret.

Corrección de la documentación upstream. La página upstream de configuración indica que los valores mínimos «posibles» son holdTimeSeconds=9 y keepAliveTimeSeconds=3. Los mínimos de la CRD son hold >= 3 y keepalive >= 1 (y keepalive <= hold). 9/3 es un ajuste agresivo recomendado, no un mínimo.

CiliumBGPAdvertisement ​

Entradas de spec.advertisements[]:

CampoNotas
advertisementTypePodCIDR, CiliumPodIPPool, Service, Interface
service.addresses[]Debe incluir al menos uno entre LoadBalancerIP, ClusterIP y ExternalIP. Obligatorio para el tipo Service
service.aggregationLengthIPv4 / IPv6De 0 a 31 / de 0 a 127; agrega rutas en vez de usar /32 y /128
interface.nameObligatorio para el tipo Interface
selectorLabelSelector para Services (o pools). Si no se define, no selecciona nada en tipos distintos de PodCIDR. No debe definirse para PodCIDR
attributes.communitiesstandard[], wellKnown[], large[]
attributes.localPreferenceSolo se envía a peers iBGP

La validación CEL exige: service para Service, interface para Interface y ningún selector para PodCIDR.

CiliumBGPNodeConfig (salida del operador) ​

spec refleja la configuración resuelta (incluye routerID y localAddress). status.bgpInstances[].peers[] contiene name, peerAddress, peerASN, peeringState, establishedTime, timers.appliedHoldTimeSeconds / appliedKeepaliveSeconds y routeCount[] (afi, safi, recibidas y anunciadas). La condición cilium.io/BGPReconcileError informa de fallos de reconciliación. Es la fuente adecuada para automatización y alertas porque no requiere ejecutar comandos dentro del agente.

CiliumBGPNodeConfigOverride ​

metadata.name debe ser igual al nombre del nodo; los nombres de instancias y peers deben coincidir con los de la configuración del clúster.

CampoNotas
spec.bgpInstances[].nameCoincide con el nombre de instancia en la configuración del clúster
.routerIDCadena con una dirección IPv4
.localPortAnulación del puerto de escucha
.localASNDe 1 a 4294967295; permite ASN por nodo o por rack
.peers[].nameCoincide con el peer de la configuración del clúster
.peers[].localAddressFuerza la dirección de origen y, por tanto, el enlace de salida; de forma predeterminada se consulta la ruta hacia el peer
.peers[].localPortPuerto de origen para la conexión

2.4 Ajustes de peer en la práctica ​

Temporizadores. Los valores predeterminados son 120/90/30 (reintento de conexión/hold/keepalive). Sin BFD, el tiempo hold es el único detector de fallos para peers que no están conectados directamente; por eso son habituales valores agresivos como 9/3 en enlaces a ToR. La contrapartida es más tráfico keepalive y mayor sensibilidad a pausas de CPU del agente.

Graceful Restart. Con gracefulRestart.enabled: true, Cilium actúa como speaker en reinicio (RFC 4724, además de reinicio elegante RFC 8538 con Notification). Cuando se reinicia el agente, el peer conserva las rutas aprendidas hasta que vence restartTimeSeconds, por lo que el plano de datos (que sigue funcionando en eBPF) no queda en agujero negro durante una actualización del agente. Define restartTimeSeconds por encima del peor tiempo de reinicio del agente, incluida la descarga de la imagen; descarga previamente las imágenes antes de actualizar. Coste: si un nodo deja de funcionar realmente, GR conserva sus rutas hasta que venza ese tiempo, así que durante ese periodo el tráfico de VIP con externalTrafficPolicy: Cluster aún puede dirigirse a un nodo caído.

Multisalto. ebgpMultihop: N define el TTL de las sesiones eBGP con peers a más de un salto (por ejemplo, un ToR con peer por loopback o un servidor de rutas). No afecta a iBGP.

MD5.

bash
kubectl -n kube-system create secret generic bgp-auth \
  --from-literal=password='<value from your secret store>'

Haz referencia a él con authSecretRef: bgp-auth. Una contraseña incorrecta aparece como dial: i/o timeout, no como error de autenticación, porque el kernel descarta los segmentos con firmas incorrectas. Si falta el Secret, la sesión no se detiene: Cilium continúa con una contraseña vacía, registra un error y establece cilium.io/MissingAuthSecret. MD5 no funciona si la sesión atraviesa NAT.

Sin BFD. Ninguna versión de Cilium de 1.18 a 1.21-pre admite BFD. Mitigaciones: temporizadores hold bajos, un enlace conectado directamente (TCP se cierra al caer el enlace), Graceful Restart para reinicios del agente y hashing resiliente/Maglev (más adelante).

2.5 Anuncios ​

PodCIDR ​

Anuncia el PodCIDR asignado al nodo (no el pool entero). Solo tiene efecto con modos IPAM que asignan un PodCIDR a cada nodo: cluster-pool y ámbito de host de Kubernetes. Con ENI, Azure y otros IPAM de nube, el anuncio PodCIDR no tiene efecto: las IP de Pod son direcciones de VPC (o VNet), no prefijos por nodo administrados por Cilium, y la infraestructura de nube ya las enruta. Consulta el análisis detallado de IPAM.

CiliumPodIPPool ​

Se usa con IPAM de varios pools. selector coincide con las etiquetas del pool; las claves especiales io.cilium.podippool.namespace e io.cilium.podippool.name seleccionan por identidad del pool. Solo se anuncian los CIDR asignados realmente a un CiliumNode. En 1.20.2, el código BGP observa v2alpha1.CiliumPodIPPool; [Versión preliminar 1.21] CiliumPodIPPool pasa a cilium.io/v2 y BGP se actualiza también (pkg/bgp/manager/reconciler/pod_ip_pool.go en v1.21.0-pre.3).

Service ​

De forma predeterminada, las rutas son exactamente /32 o /128.

OrigenSe obtiene dePolítica de tráfico respetada
LoadBalancerIP.status.loadBalancer.ingress[].ipSolo externalTrafficPolicy
ExternalIP.spec.externalIPs (con KPR requiere externalIPs.enabled)Solo externalTrafficPolicy
ClusterIP.spec.clusterIP(s) (el acceso externo requiere el ajuste BPF «External access to ClusterIP services»)Solo internalTrafficPolicy

Claves especiales de selector: io.kubernetes.service.namespace e io.kubernetes.service.name.

Interacción con la política de tráfico.

PolíticaDesde dónde se anuncia
ClusterDesde todos los nodos seleccionados por la configuración del clúster
LocalSolo desde nodos con al menos un backend local listo; la ruta sigue a los Pods

Si hay cero backends: con externalTrafficPolicy: Cluster, la VIP sigue anunciándose desde todos los nodos si --enable-no-service-endpoints-routable=true (predeterminado); de lo contrario, se retira. Con Local, se retira.

loadBalancerClass. Cilium anuncia un Service solo si la clase no está definida o es io.cilium/bgp-control-plane. Ignora los Services administrados por otra clase (por ejemplo, service.k8s.aws/nlb).

Anuncios superpuestos (1.18 y posteriores). Si varios anuncios coinciden con un Service, las comunidades se combinan como unión y se usa el valor máximo de localPreference. Antes de 1.18 ganaba la última coincidencia.

Agregación. Se ignora aggregationLengthIPv4/6 con la política de tráfico Local. Problemas conocidos: bucle de enrutamiento para VIP sin asignar dentro de un rango agregado y comportamiento indefinido si dos anuncios generan el mismo agregado con atributos distintos (cilium/cilium#37623, #40585).

ECMP. Anuncia la misma VIP desde varios nodos; se aplica el límite de rutas ECMP del enrutador. Si se pierde un nodo, se redistribuyen los flujos, salvo que el enrutador use hashing resiliente. Maglev de Cilium mantiene constante la selección del backend entre nodos con política Cluster.

Interface (1.19 y posteriores) ​

Anuncia las direcciones de una interfaz local como rutas /32 y /128. Se excluyen: rango loopback, multicast, IPv6 de enlace local y direcciones v4-mapped. La interfaz debe estar habilitada administrativamente y su estado operativo debe ser up o unknown. Cilium no configura la dirección; un uso habitual es una interfaz dummy con una dirección estable de nodo o anycast.

Atributos ​

AtributoValores
communities.standard"65000:99" o un número decimal de 4 bytes
communities.wellKnowninternet, planned-shut, accept-own, route-filter-translated-v4, route-filter-v4, route-filter-translated-v6, route-filter-v6, llgr-stale, no-llgr, blackhole, no-export, no-advertise, no-export-subconfed, no-peer
communities.large"A:B:C"
localPreferenceSolo iBGP; el atributo se omite para peers eBGP

Cilium crea políticas de exportación de GoBGP por combinación de (peer, familia y tipo de anuncio), por ejemplo 65000-ipv4-PodCIDR, además de una política de importación allow-local. Son internas. v2 no ofrece CRD de políticas de rutas, listas de prefijos, AS-prepend, MED ni next-hop; usa comunidades como punto de integración e implementa la política en el ToR (route-maps que seleccionen por comunidad).

2.6 Ejemplo completo: eBGP por rack con dos ToR ​

Las direcciones y los ASN son ejemplos.

yaml
apiVersion: cilium.io/v2
kind: CiliumBGPClusterConfig
metadata: {name: rack0}
spec:
  nodeSelector: {matchLabels: {rack: rack0}}
  bgpInstances:
  - name: instance-65001
    localASN: 65001
    peers:
    - {name: tor1, peerASN: 65000, peerAddress: 10.10.0.1, peerConfigRef: {name: tor-peer}}
    - {name: tor2, peerASN: 65000, peerAddress: 10.10.0.2, peerConfigRef: {name: tor-peer}}
---
apiVersion: cilium.io/v2
kind: CiliumBGPPeerConfig
metadata: {name: tor-peer}
spec:
  timers: {connectRetryTimeSeconds: 5, holdTimeSeconds: 9, keepAliveTimeSeconds: 3}
  gracefulRestart: {enabled: true, restartTimeSeconds: 120}
  authSecretRef: bgp-auth
  families:
  - afi: ipv4
    safi: unicast
    advertisements: {matchLabels: {advertise: bgp}}
---
apiVersion: cilium.io/v2
kind: CiliumBGPAdvertisement
metadata: {name: svc-and-pods, labels: {advertise: bgp}}
spec:
  advertisements:
  - advertisementType: PodCIDR
    attributes: {communities: {standard: ["65001:100"]}}
  - advertisementType: Service
    service: {addresses: [LoadBalancerIP]}
    selector: {matchLabels: {bgp: "true"}}
    attributes: {communities: {large: ["65001:1:100"]}}

Anulación por nodo (el nombre del nodo se coloca en metadata.name):

yaml
apiVersion: cilium.io/v2
kind: CiliumBGPNodeConfigOverride
metadata: {name: <node-name>}
spec:
  bgpInstances:
  - name: instance-65001
    routerID: "192.168.10.1"
    localPort: 1790
    localASN: 65010
    peers:
    - {name: tor1, localAddress: 10.10.0.11}

2.7 Router ID ​

ModoCómo se elige el ID
defaultDirección IPv4 del nodo (IPv4 y doble pila); en nodos solo IPv6, los 32 bits inferiores de la MAC de cilium_host
ip-poolSe asigna desde bgpControlPlane.routerIDAllocation.ipPool (un CIDR IPv4)
Manual (NodeConfigOverride.routerID)No se valida en modo default; en modo ip-pool no debe entrar en conflicto si está dentro del pool

2.8 Inspección ​

Primero, consulta el estado (no es necesario ejecutar comandos dentro del Pod):

bash
kubectl get ciliumbgpclusterconfigs,ciliumbgppeerconfigs,ciliumbgpadvertisements,ciliumbgpnodeconfigs
kubectl get ciliumbgpnodeconfigs <node> \
  -o jsonpath='{.status.bgpInstances[*].peers[*].peeringState}'
kubectl describe ciliumbgpclusterconfig rack0

CLI. cilium bgp peers [-o json|summary] [--node N] y cilium bgp routes <available|advertised|received> <afi> <safi> funcionan en 1.20.2. Llaman a la API REST del agente, obsoleta desde 1.20 (consulta abajo); en las fuentes incluidas de 1.21.0-pre.3, la CLI todavía ejecuta cilium bgp peers -o json dentro del Pod del agente.

Hive shell (preferido desde 1.20). Las notas de actualización 1.20 de upstream indican que se desaconsejan los comandos cilium-dbg bgp y las consultas de peers, rutas y políticas de rutas por la API REST local; se prefieren los comandos BGP de Hive shell. El binario del agente es cilium-dbg:

bash
kubectl -n kube-system exec ds/cilium -- cilium-dbg shell -- bgp/peers
kubectl -n kube-system exec ds/cilium -- cilium-dbg shell -- bgp/routes out ipv4 unicast
kubectl -n kube-system exec ds/cilium -- cilium-dbg shell -- bgp/route-policies
ComandoSignificado
bgp/peers [-f table|table-json|json|detailed] [-o file] [--no-uptime]Tabla de sesiones
bgp/routes <loc|in|out> <afi> <safi> [-a|--with-attrs] [--no-age] [-f ...]loc = Loc-RIB, in = Adj-RIB-In, out = Adj-RIB-Out
bgp/route-policies [-i instance]Políticas de exportación/importación generadas por Cilium

Los mismos tres comandos están en 1.20.2 y 1.21.0-pre.3 (pkg/bgp/commands/cell.go). La CLI cilium no tiene un subcomando shell; usa cilium-dbg dentro del Pod del agente.

Registros. Agente: subsys=bgp-control-plane; operador: subsys=bgp-cp-operator.

Métricas (agente, prefijo cilium_bgp_control_plane_): session_state (1 = establecida), advertised_routes, received_routes (etiquetas instance_name, local_asn, neighbor, neighbor_asn, afi, safi), reconcile_errors_total{instance_name} y reconcile_run_duration_seconds{instance_name}. Operador: cilium_operator_bgp_control_plane_reconcile_errors_total{resource_kind,resource_name} y ..._reconcile_run_duration_seconds.

Cambio de etiqueta de métrica. La página de métricas de 1.19.8 usa la etiqueta vrouter; la de 1.20.2 usa instance_name. Las notas de actualización de 1.20 no mencionan el cambio de nombre, por lo que los paneles y las alertas que usan vrouter dejan de coincidir silenciosamente tras actualizar de 1.19 a 1.20. Actualízalos como parte de la actualización.

2.9 Eliminación de v1 y cronología de las versiones de CRD ​

VersiónEstado
1.18CiliumBGPPeeringPolicy (v1) queda obsoleta; si v1 y v2 coinciden con un nodo, tiene prioridad PeeringPolicy. Las CRD BGP v2alpha1 quedan obsoletas en favor de cilium.io/v2
1.19Se eliminan la CRD v1 y el plano de control (pkg/bgpv1); migra antes de actualizar
1.20Las copias v2alpha1 de las CRD BGP v2 siguen disponibles, pero están obsoletas
1.21-preIgual

Se eliminó el campo spec.transport.localPort de la PeerConfig v2alpha1, disponible antes de 1.19; la configuración del puerto ahora se define en la instancia de configuración del clúster (localPort) y en la anulación.

2.10 Operaciones y escenarios de fallo ​

EventoComportamientoMitigación
Reinicio o actualización del agenteSe interrumpe la sesión (el speaker se ejecuta en el agente); el plano de datos sigue reenviando tráficoGraceful Restart, restartTimeSeconds mayor que el arranque del agente; descarga previamente la imagen nueva
Caída del nodoEl peer espera el tiempo hold (más el tiempo de reinicio con GR)Temporizadores hold bajos; ECMP con hashing resiliente
Caída del enlace, conexión directaTCP se cierra de inmediaton/a
Caída del enlace, varios saltosTemporizador hold (90 s de forma predeterminada)Reduce el tiempo hold; no hay BFD
Caída del operadorNo se crea ningún CiliumBGPNodeConfig; el operador tampoco asigna PodCIDR ni IP de LBAlta disponibilidad del operador
Un Service pierde todos sus backendsConsulta la sección 2.5Elige la política deliberadamente

Procedimiento de apagado de nodos. Drena el nodo; quítalo de la configuración del clúster cambiando su etiqueta para que deje de coincidir con nodeSelector (la sesión se cierra con una notificación); espera a que el peer retire la ruta (de inmediato o cuando venza el temporizador de rutas obsoletas de RFC 8538); prevé algunos reinicios por nuevo hashing ECMP.

[Versión preliminar 1.21] El controlador BGP espera a que se adjunten los programas BPF del plano de datos del host y se rellenen los mapas LB antes de anunciar rutas (pkg/bgp/agent/datapath_waiter.go). Así se cierra el intervalo que existía tras arrancar el agente en que se anunciaban rutas antes de poder atender tráfico. No está en 1.20.

2.11 Topología de referencia: ToR local ​

            [ upstream L3 / firewall ]
                 |            |
             ToR-A (AS65000) ToR-B (AS65000)    static neighbors or `bgp listen range`
              |  \  /  |     ECMP, resilient hashing, GR helper
      node1..N (Cilium AS65001, one CiliumBGPClusterConfig per rack)
        advertise: PodCIDR (cluster-pool / host-scope IPAM)
                 + Service LoadBalancerIP (from an LB IPAM pool)
        eTP: Cluster (all nodes; add Maglev) or Local (only nodes with backends)

Lista de diseño: una configuración de clúster por rack (cada nodo puede coincidir con una sola); dos peers por rack; hold 9 / keepalive 3 con GR y un tiempo de reinicio superior al arranque del agente; MD5 mediante authSecretRef; comunidades que distingan rutas de Pod y de Service para los route-maps del ToR; verifica la cantidad máxima de rutas ECMP del ToR; no hay BFD.

2.12 BGP y AWS ​

En un clúster EKS que usa IPAM ENI, las IP de Pod son direcciones de VPC y la infraestructura de VPC ya las enruta; los nodos no poseen PodCIDR, así que anunciar PodCIDR no tiene efecto y la VPC no tiene un speaker BGP que acepte rutas de nodos. Por tanto, BGP se usa en AWS sobre todo con EKS Hybrid Nodes locales (consulta configuración de red para nodos híbridos), donde el peer es el ToR local. Los ejemplos existentes de nodos híbridos de este repositorio usan API v2alpha1 porque están fijados a una compilación 1.18; en 1.19 y posteriores, usa cilium.io/v2.

3. LB IPAM ​

Madurez: CRD estable CiliumLoadBalancerIPPool de cilium.io/v2 (v2 es la versión de almacenamiento en 1.18.14, aunque v2alpha1 aún se sirve; v2alpha1 se marca obsoleta por primera vez en 1.19.8). LB IPAM está integrado en el operador y permanece inactivo hasta que se crea el primer pool (--enable-lb-ipam, predeterminado true). Solo asigna direcciones; no las anuncia.

yaml
apiVersion: cilium.io/v2
kind: CiliumLoadBalancerIPPool
metadata: {name: blue-pool}
spec:
  blocks:
  - cidr: "10.0.10.0/24"
  - start: "10.0.20.100"
    stop: "10.0.20.200"
  serviceSelector:
    matchLabels: {bgp: "true"}
---
apiVersion: v1
kind: Service
metadata: {name: web, namespace: example, labels: {bgp: "true"}}
spec:
  type: LoadBalancer
  loadBalancerClass: io.cilium/bgp-control-plane
  ports: [{port: 80}]
  selector: {app: web}

Ten en cuenta que serviceSelector está bajo spec, no bajo blocks (el ejemplo de la documentación upstream tiene una sangría incorrecta).

Campo del poolNotas
blocks[]cidr o la pareja start + stop
serviceSelectorClaves especiales io.kubernetes.service.namespace / .name
disabledPredeterminado false
allowFirstLastIPsYes o No; No reserva solo la primera y la última dirección de bloques CIDR; se ignora para /31, /32, /127, /128 y bloques start/stop

Comportamientos importantes:

  • CIDR superpuestos: el pool posterior queda marcado como conflictivo (cilium.io/PoolConflict). Las condiciones de estado son cilium.io/IPsTotal, IPsAvailable e IPsUsed; kubectl get ippools las muestra.
  • Editar un pool puede reasignar IP de Services existentes.
  • Gestión de clases: LB IPAM administra de forma predeterminada un Service LoadBalancer sin clase. defaultLBServiceIPAM de Helm acepta lbipam (valor predeterminado), nodeipam o none; con none, solo recibe una IP el Service con clase reconocida. Las clases que Cilium no reconoce se ignoran sin aviso. El Service recibe la condición cilium.io/IPAMRequestSatisfied.
  • Las familias de IP siguen ipFamilyPolicy: SingleStack (IPv4 si ambas están disponibles), PreferDualStack y RequireDualStack.
  • Solicita una dirección específica con lbipam.cilium.io/ips: "a,b" (se sigue aplicando el selector del pool; .spec.loadBalancerIP está obsoleto). No solicites la primera ni la última dirección de un pool.
  • Uso compartido: lbipam.cilium.io/sharing-key y lbipam.cilium.io/sharing-cross-namespace: "ns1,ns2"|"*". En 1.20.2, los Services pueden compartir si no hay conflictos de puerto/protocolo. [Versión preliminar 1.21] compatibilidad más estricta: no deben coincidir el puerto y protocolo, debe coincidir externalTrafficPolicy y, con Local, ambos deben seleccionar los mismos Pods, salvo que cada Service defina lbipam.cilium.io/sharing-permit-different-pods: "true" (BGP y L2 no conocen la capa 4, así que se podría descartar tráfico); deben estar en el mismo namespace, salvo que se permita compartir entre namespaces.
  • Cambio del plano de datos en 1.19: se descarta el tráfico TCP/UDP norte-sur hacia una IP LB IPAM en un puerto que ningún Service define.
  • Gateway API: Gateway.spec.addresses alimenta LB IPAM; la anotación io.cilium/lb-ipam-ips en spec.infrastructure.annotations tiene prioridad y se prevé declararla obsoleta más adelante.

La asignación de IP de Pod es independiente: consulta el análisis detallado de IPAM.

4. Anuncios L2 ​

Madurez: beta en 1.20.2 y 1.21.0-pre.3. La CRD sigue siendo CiliumL2AnnouncementPolicy de cilium.io/v2alpha1.

Un nodo elegido por Service responde a ARP (IPv4) o NDP (IPv6) por las IP externas o LoadBalancer del Service y luego balancea el tráfico con eBPF. Está dirigido a redes LAN locales sin BGP. No se aplica dentro de una VPC de AWS: la VPC no da a las VIP semántica de difusión L2 ni conmutación por error mediante ARP gratuito. Úsalo solo en entornos locales o híbridos.

yaml
l2announcements:
  enabled: true
  leaseDuration: 3s
  leaseRenewDeadline: 1s
  leaseRetryPeriod: 200ms
kubeProxyReplacement: true
k8sClientRateLimit: {qps: 32, burst: 64}
yaml
apiVersion: cilium.io/v2alpha1
kind: CiliumL2AnnouncementPolicy
metadata: {name: policy1}
spec:
  serviceSelector: {matchLabels: {color: blue}}
  nodeSelector:
    matchExpressions:
    - {key: node-role.kubernetes.io/control-plane, operator: DoesNotExist}
  interfaces: ["^eth[0-9]+"]
  externalIPs: true
  loadBalancerIPs: true
CampoNotas
nodeSelector, serviceSelectorQué nodos pueden anunciar y qué Services
interfaces[]Expresiones regulares de Go (OR). No son un control de seguridad. Los dispositivos también deben estar en el conjunto --devices de Cilium
externalIPs, loadBalancerIPsBooleanos; ambos predeterminados en false

El Service no debe tener loadBalancerClass o debe tener io.cilium/l2-announcer.

Elección de líder. Se usa un Lease coordination.k8s.io por Service, llamado cilium-l2announce-<ns>-<svc> en el namespace de Cilium; el orden de llegada determina la asignación, por lo que la carga se reparte de manera desigual. El nuevo líder envía un ARP gratuito. Valores predeterminados: leaseDuration 15 s, leaseRenewDeadline 5 s y leaseRetryPeriod 2 s. Restricciones: duration > renewDeadline; renewDeadline debe ser estrictamente mayor que 1.2 (JitterFactor de elección de líder) x retryPeriod; de lo contrario, el agente registra una advertencia y cambia los temporizadores. La conmutación por error tarda entre leaseDuration - leaseRenewDeadline y leaseDuration + leaseRenewDeadline: de 10 a 20 s con los valores predeterminados, o de 2 a 4 s con 3 s/1 s/200 ms.

Carga de la API. El Lease de cada Service se renueva aproximadamente cada leaseRenewDeadline, así que calcula QPS ~ cantidad_de_services x (1 / leaseRenewDeadline) (estimación aproximada que no cuenta reintentos ni lecturas). El límite predeterminado del cliente del agente es 10 QPS / ráfaga 20 y se comparte con todo el tráfico de API del agente: con el valor predeterminado de 5 s, son unos 0,2 QPS por Service, así que unas decenas de Services con líder ya consumen buena parte del presupuesto; con temporizadores de 1 s, unos 10 Services lo agotan. Aumenta k8sClientRateLimit antes de reducir los temporizadores. RBAC necesita permisos create/get/update/list/delete para Lease.

Límites. No es compatible con externalTrafficPolicy: Local (el nodo elegido podría no tener Pods y descartaría el tráfico). Un nodo recibe todo el tráfico de una IP; no existe balanceo de carga previo al clúster.

Los anuncios L2 de IP de Pod son independientes: l2podAnnouncements.enabled y .interfacePattern (expresión regular) envían GARP/NA para las IP locales de Pod. El indicador antiguo --l2-pod-announcements-interface se eliminó en 1.19.

Inspección: kubectl -n kube-system get lease | grep cilium-l2announce; cilium-dbg shell -- db/show l2-announce; cilium-dbg shell -- db/show devices; ejecuta arping desde otro host de la LAN.

5. Node IPAM ​

Helm nodeIPAM.enabled=true (predeterminado false; operador --enable-node-ipam; reinicia el operador) publica las direcciones de los nodos en .status.loadBalancer para Services con loadBalancerClass: io.cilium/node (o defaultLBServiceIPAM: nodeipam): ExternalIP si existe; de lo contrario, InternalIP, respetando ipFamilies. La política Cluster publica todos los nodos; Local solo los que tienen Pods en EndpointSlice. Se omiten los nodos con la etiqueta node.kubernetes.io/exclude-from-external-load-balancers o el taint ToBeDeletedByClusterAutoscaler; la anotación io.cilium.nodeipam/match-node-labels limita los nodos. No funciona con política Local en Services de Cilium Ingress/Gateway (usan un EndpointSlice sintético). Úsalo solo cuando BGP y L2 no sean posibles y solo con direcciones privadas de nodo: publicar IP públicas de nodo crearía un punto de entrada público fuera de la regla que exige CloudFront.

6. Qué función administra cada Service ​

loadBalancerClassResponsableRequisitos
sin definirLB IPAM de forma predeterminada (defaultLBServiceIPAM)Un pool; además, BGP o L2 para que sea accesible
io.cilium/bgp-control-planeLB IPAM + anuncio BGPBGP Control Plane
io.cilium/l2-announcerLB IPAM + anuncio L2Anuncios L2
io.cilium/nodeNode IPAMnodeIPAM.enabled
service.k8s.aws/nlbAWS Load Balancer ControllerCilium BGP/LB IPAM lo ignora

7. Egress Gateway ​

Madurez: CiliumEgressGatewayPolicy usa cilium.io/v2 (ámbito de clúster, nombre abreviado cegp); la documentación 1.20 no la marca como beta.

El tráfico de los Pods seleccionados hacia los CIDR de destino seleccionados se reenvía a un nodo de gateway y se aplica SNAT a una IP de origen estable, de modo que el firewall externo vea una dirección predecible.

Requisitos: egressGateway.enabled=true, bpf.masquerade=true y kubeProxyReplacement=true; reinicia los agentes y el operador. No es compatible con el modo de identidad kvstore (usa crd), ClusterMesh (el gateway debe estar en el mismo clúster) ni CiliumEndpointSlice. --enable-ipv4-egress-gateway se eliminó en 1.19.

yaml
apiVersion: cilium.io/v2
kind: CiliumEgressGatewayPolicy
metadata: {name: egress-sample}
spec:
  selectors:
  - podSelector:
      matchLabels: {org: empire, class: mediabot, io.kubernetes.pod.namespace: default}
  destinationCIDRs: ["192.0.2.0/24"]
  egressGateway:
    nodeSelector: {matchLabels: {egress-node: "true"}}
    egressIP: 10.168.60.100
CampoNotas
selectors[]podSelector y/o namespaceSelector (namespace mediante la etiqueta io.kubernetes.pod.namespace); no se permite usar solo nodeSelector
destinationCIDRs[], excludedCIDRs[]IPv4 e IPv6; los CIDR excluidos deben ser subconjuntos. Las direcciones internas (Pods, nodos y servidor de API) siempre se excluyen de EGW
egressGateway.nodeSelectorObligatorio. Si hay varias coincidencias, se elige la primera en orden alfabético del nombre de nodo. Si no coincide ningún nodo, se descarta el tráfico a los CIDR de destino
egressGateway.interface / egressIPSon mutuamente excluyentes (si se configuran ambas, se ignora la política). interface usa su primera dirección IPv4/IPv6; egressIP debe existir en un dispositivo administrado por Cilium; si no se define ninguna, se usa la interfaz de la ruta predeterminada y sus primeras direcciones IPv4/IPv6
egressGateways[]Hasta 64 entradas; si no está vacío, se ignora egressGateway

Limitaciones:

  • No hay alta disponibilidad en 1.20.2 ni 1.21.0-pre.3. egressGateways[] configura varios gateways estáticos: se fija cada endpoint de origen a uno mediante un hash de su UID de CiliumEndpoint. Al cambiar el conjunto, se reasignan endpoints y se interrumpen las conexiones existentes (cilium/cilium#39245). El código fuente de ninguna versión contiene comprobaciones de estado ni conmutación automática por fallo de un gateway (búsqueda en pkg/egressgateway). La CRD de 1.21-pre solo difiere de la de 1.20.2 en los tipos de CIDR.
  • El gateway no sigue los cambios de IP posteriores a la selección; vuelve a aplicar la política.
  • Si no existe la IP configurada, se descarta el tráfico con el motivo «No Egress IP configured».
  • Un Pod nuevo puede enviar tráfico brevemente con su propia IP o con la IP del nodo antes de que se programe la política.
  • El presupuesto de puertos SNAT por cada combinación de (IP de salida, IP:puerto remoto) es de aproximadamente 65535 menos el límite superior del rango de puertos de nodo (32767 de forma predeterminada), es decir, 32768 conexiones. Consulta cilium-dbg shell -- db/show nat-stats.

Inspección: kubectl -n kube-system exec ds/cilium -- cilium-dbg bpf egress list (muestra IP de origen, CIDR de destino, IP de salida e IP de gateway).

En EKS. El nodo de gateway necesita la dirección de salida en una ENI conectada (otra ENI o una IP privada secundaria). Las IP de salida son direcciones privadas de VPC; para acceder a Internet desde ellas, enruta el tráfico mediante una gateway NAT. No asignes IP públicas ni EIP a los nodos de gateway. Con IPAM ENI, --egress-multi-home-ip-rule-compat se eliminó en 1.19; deja de usarlo primero en 1.18.

8. Local Redirect Policy ​

CiliumLocalRedirectPolicy (cilium.io/v2, con ámbito de namespace) redirige el tráfico destinado a una ClusterIP de Service o a una IP:puerto arbitraria hacia Pods backend locales al nodo.

Habilítala con localRedirectPolicies.enabled=true (la clave antigua localRedirectPolicy está obsoleta); reinicia el operador y el agente. De forma opcional, se puede configurar una lista de permitidos para todo el clúster con localRedirectPolicies.addressMatcherCIDRs (el YAML de la documentación upstream muestra una clave escrita de otra manera; la clave de Helm es addressMatcherCIDRs).

yaml
apiVersion: cilium.io/v2
kind: CiliumLocalRedirectPolicy
metadata: {name: lrp-svc}
spec:
  redirectFrontend:
    serviceMatcher: {serviceName: my-service, namespace: default}
  redirectBackend:
    localEndpointSelector: {matchLabels: {app: proxy}}
    toPorts: [{port: "80", protocol: TCP}]
SelectorUso
serviceMatcherSolo Services ClusterIP; reemplaza la entrada del Service por tipo LocalRedirect y usa únicamente backends locales al nodo
addressMatcher{ip, toPorts[]}IP que no pertenece a un Service; se niega a anular un frontend ClusterIP existente

Reglas: los Pods backend deben estar en el namespace de la política; si se usan varios puertos, deben tener nombre; solo se redirigen las conexiones nuevas (reinicia los clientes); las políticas no se pueden actualizar (elimínalas y vuelve a crearlas). Configuraciones compatibles de reemplazo de kube-proxy: KPR completo; KPR con socketLB.hostNamespaceOnly=true; KPR desactivado con socketLB.enabled=true; o KPR desactivado sin más (solo Pod a ClusterIP). El caso de uso principal es DNS local al nodo (el frontend kube-dns se redirige a un Pod node-local-dns en su propio namespace de red). Inspecciona con cilium-dbg lrp list.

9. Distribución del tráfico de Services ​

loadBalancer.serviceTopology (predeterminado false, indicador --enable-service-topology) hace que el reemplazo de kube-proxy respete los hints de enrutamiento consciente de la topología y spec.trafficDistribution. PreferSameZone (y el alias obsoleto PreferClose) usa los hints de zona de EndpointSlice comparados con la etiqueta de zona topology.kubernetes.io/zone del nodo; PreferSameNode prefiere backends del nodo local y, si no hay ninguno que cumpla, recurre al comportamiento predeterminado. [Versión preliminar 1.21] solo cuentan como candidatos los backends activos (listos). Esto difiere de externalTrafficPolicy / internalTrafficPolicy: Local, que restringen los destinos en vez de priorizarlos. En EKS de varias zonas de disponibilidad, serviceTopology: true más trafficDistribution: PreferSameZone reduce el tráfico entre zonas. En Gateway API, CiliumGatewayClassConfig.spec.service.trafficDistribution se propaga al Service generado.

10. Puntos de entrada de capa 7: Ingress y Gateway API ​

Requisitos previos: kubeProxyReplacement=true, l7Proxy=true (valor predeterminado), compatibilidad con TPROXY (iptables de forma predeterminada; bpf.tproxy=true es beta y elimina la dependencia de iptables) y compatibilidad con Services LoadBalancer (o modo de red del host, desde 1.16).

Flujo del tráfico. eBPF intercepta los paquetes dirigidos al puerto del Service y los redirige mediante TPROXY al Envoy de cada nodo. El tráfico recibe la identidad especial ingress, por lo que la política se aplica dos veces: de world a ingress y de ingress al backend. Se conserva la IP de origen con ambos valores de externalTrafficPolicy; con Local, Cilium hace que todos los nodos superen las comprobaciones de estado en el puerto de health check. La CiliumNetworkPolicy debe permitir ambos saltos. Con TLS passthrough, los backends ven la IP de Envoy.

Ingress ​

Valor de HelmPredeterminado
ingressController.enabled / .defaultfalse / false
ingressController.loadbalancerModededicated (shared o dedicated; anotación por Ingress ingress.cilium.io/loadbalancer-mode)
ingressController.enforceHttpstrue
ingressController.useRemoteAddress, .xffNumTrustedHopstrue, 0
ingressController.ingressLBAnnotationPrefixeslbipam.cilium.io, nodeipam.cilium.io, service.beta.kubernetes.io, service.kubernetes.io, cloud.google.com (se propagan de Ingress al Service)
ingressController.service.* (compartido)name: cilium-ingress, type: LoadBalancer, externalTrafficPolicy: Cluster, anotaciones, loadBalancerClass
ingressController.hostNetwork.*enabled: false, sharedListenerPort: 8080

Gateway API ​

Cilium 1.20.2 y 1.21.0-pre.3 usan Gateway API v1.6.1 (1.19.8: v1.4.1; 1.18.14: v1.3.0). Tipos admitidos: GatewayClass, Gateway, HTTPRoute, GRPCRoute, TLSRoute, BackendTLSPolicy, ReferenceGrant, ListenerSet, TCPRoute y UDPRoute. CRD necesarias: GatewayClass, Gateway, HTTPRoute, GRPCRoute, ReferenceGrant, BackendTLSPolicy y TLSRoute. TCPRoute, UDPRoute y ListenerSet son opcionales (la función se deshabilita si faltan). Instálalas con kubectl apply --server-side.

Riesgo durante la actualización: Gateway API v1.6.1 y TLSRoute. En v1.6.1, TLSRoute pasó de v1alpha2 a v1. Las notas de actualización de 1.20 exigen v1.6.1 como versión mínima. Si ya tienes objetos TLSRoute, instala la CRD TLSRoute del canal experimental de v1.6.1 (todavía incluye la versión v1alpha2). La CRD TLSRoute del canal standard de v1.6 hace que los objetos v1alpha2 existentes no se puedan leer y parezcan desaparecer de etcd. Haz una copia de seguridad de TLSRoute y actualiza las CRD de Gateway API antes de actualizar Cilium a 1.20.

Valor de HelmPredeterminado
gatewayAPI.enabledfalse
gatewayAPI.gatewayClass.createauto
gatewayAPI.enableProxyProtocol, .enableAppProtocol, .enableAlpnfalse
gatewayAPI.useRemoteAddress, .xffNumTrustedHopstrue, 0
gatewayAPI.externalTrafficPolicyCluster (se ignora con la red del host)
gatewayAPI.secretsNamespacecreate: true, name: cilium-secrets, sync: true
gatewayAPI.hostNetwork.enabled / .nodes.matchLabelsfalse / {}

El Service generado se llama cilium-gateway-<gateway> y es de tipo LoadBalancer de forma predeterminada. Personalízalo con CiliumGatewayClassConfig (cilium.io/v2alpha1, con ámbito de namespace, referencia desde GatewayClass.parametersRef; alfa): spec.service{type, externalTrafficPolicy, loadBalancerClass, ipFamilies, ipFamilyPolicy, allocateLoadBalancerNodePorts, loadBalancerSourceRanges, loadBalancerSourceRangesPolicy, trafficDistribution}, envoy.serverHeaderTransformation y httpOptions.grpcWebTranslation.enabled. Para cada Gateway, spec.infrastructure.annotations y labels se copian al Service generado; así se pasan anotaciones service.beta.kubernetes.io/aws-load-balancer-*. No se admite spec.infrastructure.parametersRef.

Modo de red del host (gatewayAPI.hostNetwork.enabled=true): Envoy escucha en las interfaces del nodo; usa puertos superiores a 1023 o concede NET_BIND_SERVICE; es mutuamente excluyente con el modo Service LoadBalancer e incompatible con TCPRoute/UDPRoute; el Service pasa a ser NodePort; aparecen como máximo 16 direcciones en el estado de Gateway.

Patrón de EKS: origen VPC de CloudFront a NLB interno y Cilium ​

CloudFront es el único punto de entrada público. Ningún componente de esta topología está expuesto a Internet.

Internet --> CloudFront --(VPC origin)--> INTERNAL NLB (private subnets)
         --> node NodePort --> Cilium Envoy (Ingress or Gateway) --> Pods
yaml
kubeProxyReplacement: true
ingressController:
  enabled: true
  loadbalancerMode: shared
  service:
    type: LoadBalancer
    loadBalancerClass: service.k8s.aws/nlb
    allocateLoadBalancerNodePorts: true
    externalTrafficPolicy: Cluster
    annotations:
      service.beta.kubernetes.io/aws-load-balancer-scheme: internal
      service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance
      service.beta.kubernetes.io/aws-load-balancer-security-groups: sg-<nlb-sg>
      service.beta.kubernetes.io/aws-load-balancer-manage-backend-security-group-rules: "true"

Para la variante de Gateway API, define CiliumGatewayClassConfig.spec.service.loadBalancerClass: service.k8s.aws/nlb y coloca las mismas anotaciones aws-load-balancer-* en Gateway.spec.infrastructure.annotations.

Reglas de este patrón:

  • scheme: internal es obligatorio. Nunca uses internet-facing.
  • Usa target-type: instance. El Service Ingress compartido de Cilium usa un EndpointSlice sintético, así que los destinos ip no se resuelven a Pods; consulta Ingress y Gateway API.
  • El grupo de seguridad del balanceador solo admite CloudFront: el grupo de seguridad administrado por el servicio CloudFront-VPCOrigins-Service-SG (se crea al crear el origen VPC; más restrictivo y preferido; no asignes tú mismo ese prefijo a un grupo) o la lista de prefijos administrada por CloudFront com.amazonaws.global.cloudfront.origin-facing (y com.amazonaws.global.ipv6.cloudfront.origin-facing para doble pila). No permitas entrada desde 0.0.0.0/0 o ::/0, ni asignes IP públicas o EIP a los nodos (AWS: orígenes VPC).
  • Los grupos de seguridad de nodo solo admiten el grupo de seguridad del NLB en el rango NodePort, no un CIDR abierto a Internet.

11. SRv6 y enrutamiento estático ​

SRv6 no está disponible como función compatible. Las fuentes de 1.20.2 y 1.21.0-pre.3 no tienen página de documentación, clave Helm ni CRD para ello; solo quedan ocultos el indicador del agente --enable-srv6, los hooks BPF y los comandos de inspección cilium-dbg bpf srv6, sin plano de control de código abierto. No planifiques usarlo. Para rutas estáticas, usa enrutamiento nativo con autoDirectNodeRoutes o tablas de rutas de nube (parte 9).

Laboratorios ​

Los laboratorios 1 a 4 requieren un entorno local (kind o unas pocas máquinas virtuales) con un contenedor de enrutador, como FRR; el laboratorio 5 usa una cuenta de AWS de pruebas desechable mediante --profile <SANDBOX_PROFILE>. Los resultados esperados se describen con palabras; no se incluyen salidas capturadas.

Laboratorio 1: sesión BGP con un ToR FRR ​

Requisitos previos: clúster kind con 2 nodos de trabajo en una red Docker compartida con un contenedor FRR (AS 65000, peers configurados para las IP de los nodos, AS remoto 65001); Cilium con bgpControlPlane.enabled=true; manifiestos de la sección 2.6 adaptados a las IP de tus nodos (quita authSecretRef o crea primero el Secret).

  1. Etiqueta los nodos de trabajo con rack=rack0; aplica ClusterConfig, PeerConfig y Advertisement.
  2. kubectl get ciliumbgpnodeconfigs muestra uno por cada nodo etiquetado.
  3. kubectl get ciliumbgpnodeconfigs <node> -o jsonpath='{.status.bgpInstances[*].peers[*].peeringState}' y cilium-dbg shell -- bgp/peers deben informar established; show bgp summary de FRR debe mostrar activos los peers.
  4. cilium-dbg shell -- bgp/routes out ipv4 unicast muestra el PodCIDR del nodo; show ip route bgp de FRR confirma que se aprendió.
  5. Elimina el Pod del agente de un nodo. Con GR habilitado, FRR debe conservar las rutas (marcadas como obsoletas) hasta el vencimiento del tiempo de reinicio; sin GR, desaparecen enseguida. Compara ambos casos.

Reversión/limpieza: elimina los tres recursos BGP y quita las etiquetas de los nodos. Al eliminar ClusterConfig, el operador quita los NodeConfig y cierra las sesiones.

Laboratorio 2: LB IPAM con BGP e interacción con la política de tráfico ​

Requisitos previos: laboratorio 1 en ejecución.

  1. Crea el pool y el Service de la sección 3 (usa un bloque dentro de un rango que acepte tu contenedor FRR).
  2. kubectl get svc web -n example muestra una EXTERNAL-IP del pool; kubectl get ippools muestra IPsUsed igual a 1.
  3. bgp/routes out ipv4 unicast muestra el /32 desde cada nodo seleccionado. Desde el contenedor FRR, ejecuta curl <VIP>.
  4. Ejecuta kubectl patch svc web -n example -p '{"spec":{"externalTrafficPolicy":"Local"}}'. La ruta solo debe permanecer en los nodos con un Pod listo; escala el Deployment y observa cómo cambia.

Limpieza: elimina el Service, el Deployment y el pool.

Laboratorio 3: anuncios L2 ​

Requisitos previos: clúster kind sobre un puente Linux, KPR habilitado, l2announcements.enabled=true con temporizadores 3 s/1 s/200 ms y límite de tasa del cliente aumentado; un contenedor cliente en el mismo puente.

  1. Aplica la política L2 y un Service LoadBalancer de un pool.
  2. kubectl -n kube-system get lease | grep cilium-l2announce muestra un Lease para el Service; arping desde el cliente devuelve la MAC del nodo líder.
  3. Elimina el Pod del agente de Cilium en el nodo líder (o detén el contenedor de ese nodo) y mide cuánto falla arping: con estos temporizadores, espera unos segundos; con los valores predeterminados, de 10 a 20 segundos.

Limpieza: elimina la política y el Service. Reversión: restablece los valores predeterminados del Lease.

Laboratorio 4: Egress Gateway ​

Requisitos previos: KPR y bpf.masquerade=true, egressGateway.enabled=true, agentes y operador reiniciados; un servidor web externo en un contenedor que registre las IP de los clientes; un nodo etiquetado egress-node=true con una dirección secundaria en su dispositivo.

  1. Aplica una política similar a la de la sección 7 con esa dirección y el CIDR del servidor.
  2. Desde un Pod seleccionado, ejecuta curl al servidor; el registro debe mostrar la IP de salida en vez de la IP del nodo o del Pod.
  3. cilium-dbg bpf egress list en el nodo de origen muestra la entrada. Quita la etiqueta del nodo: se debería descartar el tráfico al CIDR (no habrá gateway).

Limpieza/reversión: elimina la política y quita la etiqueta. Mientras esté aplicada, interrumpe el tráfico seleccionado.

Laboratorio 5: NLB interno de EKS detrás de CloudFront (cuenta de pruebas) ​

Requisitos previos: aws sts get-caller-identity --profile <SANDBOX_PROFILE> muestra la cuenta de pruebas esperada <ACCOUNT_ID> y el rol asumido previsto; un clúster EKS con Cilium y AWS Load Balancer Controller; ya se creó un origen VPC de CloudFront.

  1. Instala con los valores de Helm de la sección 10 (si lo prefieres, usa la variante Gateway API).
  2. aws elbv2 describe-load-balancers --profile <SANDBOX_PROFILE> --query 'LoadBalancers[].[LoadBalancerName,Scheme]' debe mostrar internal para el NLB nuevo.
  3. aws ec2 describe-security-groups --profile <SANDBOX_PROFILE> --group-ids <nlb-sg> --query 'SecurityGroups[].IpPermissions' debe mostrar como orígenes solo el grupo de seguridad o la lista de prefijos de origen VPC de CloudFront, nunca 0.0.0.0/0 ni ::/0.
  4. Configura el NLB como destino del origen VPC y envía una solicitud mediante el dominio de CloudFront.

Limpieza: elimina el Ingress o Gateway (el controlador elimina el NLB); luego verifica que el NLB se haya eliminado con una respuesta real de recurso no encontrado, no solo con estado deleting.

Diferencias entre versiones ​

Área1.181.191.201.21-pre
BGP v1 CiliumBGPPeeringPolicyobsoletaeliminadaeliminadaeliminada
CRD de BGPv2 (y v2alpha1)almacenamiento cilium.io/v2; v2alpha1 obsoletaigualigual
Anuncio BGP Interface, transport.sourceInterfaceno aparecen en la documentacióndisponiblesdisponiblesdisponibles
GoBGPn/a en esta revisióngobgp v3 (1.19.8)gobgp v4gobgp v4
Etiqueta de métrica BGPn/avrouter (documentación)instance_nameinstance_name
Listado por cilium-dbg bgp / RESTcompatiblecompatibleobsoleto; usa Hive shell bgp/*marcado obsoleto
Espera a que el plano de datos esté listo antes de anunciar BGPnononosí
CiliumLoadBalancerIPPoolv2 (almacenamiento), v2alpha1 aún disponiblecilium.io/v2 (v2alpha1 obsoleta)v2v2; reglas de uso compartido más estrictas
CRD de Gateway APIv1.3.0v1.4.1v1.6.1 (riesgo con TLSRoute)v1.6.1
API CiliumPodIPPoolv2alpha1v2alpha1v2alpha1v2
Egress GatewayCRD v2se eliminan --enable-ipv4-egress-gateway y --egress-multi-home-ip-rule-compatsin alta disponibilidadsin alta disponibilidad
Anuncios L2betabetabeta (CRD v2alpha1)beta
SRv6ausenteausenteausenteausente (solo queda un indicador oculto)

Solución de problemas ​

SíntomaCausa probableComprobación
No se crea CiliumBGPNodeConfigel operador no se ejecuta o nodeSelector no coincide con ningún nodoCondición de ClusterConfig NoMatchingNode; registros del operador subsys=bgp-cp-operator
Se rechaza la configuración del clústerotra configuración del clúster selecciona el mismo nodoConflictingClusterConfig
La sesión queda atascada; dial: i/o timeoutcontraseña MD5 incorrecta, ACL o dirección de origen incorrectaauthSecretRef, cilium.io/MissingAuthSecret, localAddress / sourceInterface
La sesión está activa, pero no hay rutaslas etiquetas de families[].advertisements en PeerConfig no coinciden con las etiquetas del anuncioCompara las etiquetas; consulta bgp/route-policies
PodCIDR no anunciado en EKSIPAM ENI no asigna PodCIDR por nodoIPAM
VIP de Service no anunciadaloadBalancerClass no es io.cilium/bgp-control-plane ni está vacío, no coincide el selector o la política Local no tiene un backend listoYAML del Service; bgp/routes out
Las rutas desaparecen al actualizar el agenteno se habilitó Graceful Restart o el tiempo de reinicio es demasiado breveGR de PeerConfig; descarga previamente la imagen
Los paneles BGP de Grafana quedan vacíos tras 1.20la etiqueta vrouter cambió a instance_nameActualiza las consultas
La IP LB permanece en <pending>no hay pool, no coincide el selector, el pool está en conflicto o la clase es desconocidakubectl get ippools; condición del Service
La VIP L2 fluctúa o fallapolítica Local o limitación de solicitudes de API del LeaseObjetos Lease; aumenta k8sClientRateLimit
Se descarta el tráfico de salidaningún nodo coincide con nodeSelector del gateway o falta la IP en el dispositivobpf egress list; motivo del descarte
TLSRoute desaparece tras actualizar la CRD de Gateway APIse instaló la CRD v1.6 del canal estándar sobre datos v1alpha2Restaura desde la copia de seguridad; usa la CRD del canal experimental
El Service de Gateway queda atascadofaltan CRD requeridas de Gateway API o KPR está desactivadoRegistros del operador; cilium status

Límites de validación y fuentes ​

En esta revisión no se ejecutaron los laboratorios en un clúster activo; se contrastaron con el código fuente y la documentación upstream. La sintaxis de bgp/peers y bgp/routes se verificó en pkg/bgp/commands; no se capturó la salida real de las tablas y, por tanto, no se muestra. Se omitieron temas no investigados sobre BGP con clústeres EKS nativos (no híbridos), como Transit Gateway Connect o el peering de VPC Route Server. Sin verificar: si Egress Gateway incorporará conmutación por error según estado en 1.21 GA, y la versión exacta de 1.19 a 1.20 que cambió la etiqueta de métrica (se confirmó en 1.20.2 y no aparece en la documentación de 1.19.8).

Fuentes (etiqueta v1.20.2, salvo que se indique otra):

Cuestionario ​

Pon a prueba tus conocimientos con el cuestionario de la parte 11.

Pregunta a la documentación

Enter envía, Shift+Enter añade una línea.