1 Pre-conocimiento
1.1 Introducción a Cilio
Cilium es un complemento CNI de Kubernetes basado en la tecnología eBPF. Cilium posiciona el producto como "Redes, observabilidad y seguridad basadas en eBPF" en su sitio web oficial , y se compromete a proporcionar redes, observabilidad y seguridad basadas en eBPF para cargas de trabajo de contenedores una variedad de soluciones Al insertar dinámicamente alguna lógica de control dentro de Linux utilizando la tecnología eBPF, Cilium se puede aplicar y actualizar sin modificar el código de la aplicación o la configuración del contenedor, lo que permite funciones relacionadas con la red, la observabilidad y la seguridad.
1.2 Introducción a Cilium BGP
BGP (Border Gateway Protocol, Border Gateway Protocol) es un protocolo de enrutamiento dinámico utilizado entre AS (Sistema autónomo, sistema autónomo). El protocolo BGP proporciona estrategias de control de enrutamiento ricas y flexibles, y se utilizó principalmente para la interconexión entre AS de Internet en los primeros días. Con el desarrollo de la tecnología, el protocolo BGP también se ha utilizado ampliamente en los centros de datos.Las redes modernas de centros de datos generalmente se basan en la arquitectura de hoja espinal, en la que BGP se puede usar para propagar la información de accesibilidad de los puntos finales.
La capa de hoja consta de conmutadores de acceso que agregan el tráfico de los servidores y se conectan directamente a la columna vertebral o al núcleo de la red. Los conmutadores de columna están interconectados con todos los conmutadores de hoja en una topología de malla completa.
Con la creciente aplicación de Kubernetes en las empresas, estos puntos finales pueden ser Kubernetes Pods. Para permitir que la red fuera del clúster de Kubernetes obtenga dinámicamente las rutas de los Pods accedidos a través del protocolo BGP, es obvio que Cilium debe introducir soporte para el Protocolo BGP. .
En Cilium, BGP se introdujo por primera vez en la versión 1.10 Al asignar un servicio de tipo LoadBalancer a las aplicaciones y combinarlo con MetalLB, la información de enrutamiento se anuncia a los vecinos de BGP.
Sin embargo, a medida que el uso de IPv6 continúa creciendo, está claro que Cilium necesita capacidades de BGP IPv6, incluido Segment Routing v6 (SRv6). MetalLB actualmente tiene soporte limitado para IPv6 a través de FRR y aún es experimental. El equipo de Cilium evaluó varias opciones y decidió pasar a GoBGP [1] , que tiene más funciones .
En la última versión de Cilium 1.12, habilitar la compatibilidad con BGP solo requiere configurar --enable-bgp-control-plane=true
parámetros , y un nuevo CRD CiliumBGPPeeringPolicy
permite una configuración más detallada y extensible.
- La misma configuración de BGP se puede aplicar a varios nodos utilizando la selección de
nodeSelector
parámetros por etiqueta. - Cuando el
exportPodCIDR
parámetro se establece en verdadero, todos los CIDR de pod se pueden anunciar dinámicamente sin especificar manualmente qué prefijos de ruta deben anunciarse. neighbors
Los parámetros se utilizan para configurar la información del vecino BGP, generalmente dispositivos de red fuera del clúster.
apiVersion: "cilium.io/v2alpha1"
kind: CiliumBGPPeeringPolicy
metadata:
name: rack0
spec:
nodeSelector:
matchLabels:
rack: rack0
virtualRouters:
- localASN: 65010
exportPodCIDR: true
neighbors:
- peerAddress: "10.0.0.1/32"
peerASN: 65010
1.3 Introducción al tipo
Kind [2] (Kubernetes en Docker) es una herramienta que utiliza contenedores Docker como nodos Node para ejecutar clústeres locales de Kubernetes. Solo necesitamos instalar Docker y podemos crear rápidamente uno o más clústeres de Kubernetes en minutos. Para facilitar el experimento, este artículo utiliza Kind para crear un entorno de clúster de Kubernetes.
1.4 Introducción a Containerlab
Containerlab [3] proporciona una solución simple, liviana y basada en contenedores para orquestar experimentos de red, compatible con varios sistemas operativos de red en contenedores, como Cisco, Juniper, Nokia, Arista, etc. Containerlab puede lanzar contenedores y crear conexiones virtuales entre ellos para construir topologías de red definidas por el usuario basadas en perfiles definidos por el usuario.
name: sonic01
topology:
nodes:
srl:
kind: srl
image: ghcr.io/nokia/srlinux
sonic:
kind: sonic-vs
image: docker-sonic-vs:2020-11-12
links:
- endpoints: ["srl:e1-1", "sonic:eth1"]
La interfaz de administración del contenedor está conectada a la red Docker de tipo puente llamada clab, y la interfaz comercial está conectada a través de las reglas de enlaces definidas en el archivo de configuración. Esto es como los modos de gestión fuera de banda y dentro de banda correspondientes a la gestión de red en el centro de datos.
Containerlab también nos proporciona una gran cantidad de casos experimentales, que se pueden encontrar en Ejemplos de laboratorio [4] . Incluso podemos crear una arquitectura de red a nivel de centro de datos a través de Containerlab (consulte la estructura Clos de 5 etapas [5] )
2 requisitos previos
Seleccione el método de instalación adecuado según la versión del sistema operativo correspondiente:
- Instale Docker: https://docs.docker.com/engine/install/
- Instalar Containerlab: https://containerlab.dev/install/
- Tipo de instalación: https://kind.sigs.k8s.io/docs/user/quick-start/#installing-with-a-package-manager
- Instale Helm: https://helm.sh/docs/intro/install/
Los archivos de configuración utilizados en este artículo se pueden obtener en https://github.com/cr7258/kubernetes-guide/tree/master/containerlab/cilium-bgp .
3 Inicie un clúster de Kubernetes con Kind
Prepare un archivo de configuración Kind y cree un clúster de Kubernetes de 4 nodos.
# cluster.yaml
kind: Cluster
name: clab-bgp-cplane-demo
apiVersion: kind.x-k8s.io/v1alpha4
networking:
disableDefaultCNI: true # 禁用默认 CNI
podSubnet: "10.1.0.0/16" # Pod CIDR
nodes:
- role: control-plane # 节点角色
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-ip: 10.0.1.2 # 节点 IP
node-labels: "rack=rack0" # 节点标签
- role: worker
kubeadmConfigPatches:
- |
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
node-ip: 10.0.2.2
node-labels: "rack=rack0"
- role: worker
kubeadmConfigPatches:
- |
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
node-ip: 10.0.3.2
node-labels: "rack=rack1"
- role: worker
kubeadmConfigPatches:
- |
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
node-ip: 10.0.4.2
node-labels: "rack=rack1"
Ejecute el siguiente comando para crear un clúster de Kubernetes a través de Kind.
kind create cluster --config cluster.yaml
Compruebe el estado del nodo del clúster. Dado que no hemos instalado el complemento CNI, el estado del nodo es NotReady.
kubectl get node
4 Iniciar Containerlab
Defina el archivo de configuración para Containerlab, cree la infraestructura de red y conéctese al clúster de Kubernetes creado por Kind:
- router0, tor0, tor1 son dispositivos de red fuera del clúster de Kubernetes y establecen la información de la interfaz de red y la configuración de BGP en el parámetro exec. router0 establece vecinos BGP con tor0, tor1, tor0 establece vecinos BGP con server0, server1, router0 y tor1 establece vecinos BGP con server2, server3, router0.
- La configuración de Containerlab
network-mode: container:<容器名>
puede compartir el espacio de nombres de red de los contenedores iniciados fuera de Containerlab y configurar los contenedores server0, server1, server2, server3 para conectarse a los 4 nodos del clúster de Kubernetes creado por Kind en la Sección 3, respectivamente.
# topo.yaml
name: bgp-cplane-demo
topology:
kinds:
linux:
cmd: bash
nodes:
router0:
kind: linux
image: frrouting/frr:v8.2.2
labels:
app: frr
exec:
- iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
- ip addr add 10.0.0.0/32 dev lo
- ip route add blackhole 10.0.0.0/8
- touch /etc/frr/vtysh.conf
- sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons
- usr/lib/frr/frrinit.sh start
- >-
vtysh -c 'conf t'
-c 'router bgp 65000'
-c ' bgp router-id 10.0.0.0'
-c ' no bgp ebgp-requires-policy'
-c ' neighbor ROUTERS peer-group'
-c ' neighbor ROUTERS remote-as external'
-c ' neighbor ROUTERS default-originate'
-c ' neighbor net0 interface peer-group ROUTERS'
-c ' neighbor net1 interface peer-group ROUTERS'
-c ' address-family ipv4 unicast'
-c ' redistribute connected'
-c ' exit-address-family'
-c '!'
tor0:
kind: linux
image: frrouting/frr:v8.2.2
labels:
app: frr
exec:
- ip link del eth0
- ip addr add 10.0.0.1/32 dev lo
- ip addr add 10.0.1.1/24 dev net1
- ip addr add 10.0.2.1/24 dev net2
- touch /etc/frr/vtysh.conf
- sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons
- /usr/lib/frr/frrinit.sh start
- >-
vtysh -c 'conf t'
-c 'frr defaults datacenter'
-c 'router bgp 65010'
-c ' bgp router-id 10.0.0.1'
-c ' no bgp ebgp-requires-policy'
-c ' neighbor ROUTERS peer-group'
-c ' neighbor ROUTERS remote-as external'
-c ' neighbor SERVERS peer-group'
-c ' neighbor SERVERS remote-as internal'
-c ' neighbor net0 interface peer-group ROUTERS'
-c ' neighbor 10.0.1.2 peer-group SERVERS'
-c ' neighbor 10.0.2.2 peer-group SERVERS'
-c ' address-family ipv4 unicast'
-c ' redistribute connected'
-c ' exit-address-family'
-c '!'
tor1:
kind: linux
image: frrouting/frr:v8.2.2
labels:
app: frr
exec:
- ip link del eth0
- ip addr add 10.0.0.2/32 dev lo
- ip addr add 10.0.3.1/24 dev net1
- ip addr add 10.0.4.1/24 dev net2
- touch /etc/frr/vtysh.conf
- sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons
- /usr/lib/frr/frrinit.sh start
- >-
vtysh -c 'conf t'
-c 'frr defaults datacenter'
-c 'router bgp 65011'
-c ' bgp router-id 10.0.0.2'
-c ' no bgp ebgp-requires-policy'
-c ' neighbor ROUTERS peer-group'
-c ' neighbor ROUTERS remote-as external'
-c ' neighbor SERVERS peer-group'
-c ' neighbor SERVERS remote-as internal'
-c ' neighbor net0 interface peer-group ROUTERS'
-c ' neighbor 10.0.3.2 peer-group SERVERS'
-c ' neighbor 10.0.4.2 peer-group SERVERS'
-c ' address-family ipv4 unicast'
-c ' redistribute connected'
-c ' exit-address-family'
-c '!'
server0:
kind: linux
image: nicolaka/netshoot:latest
network-mode: container:control-plane
exec:
- ip addr add 10.0.1.2/24 dev net0
- ip route replace default via 10.0.1.1
server1:
kind: linux
image: nicolaka/netshoot:latest
network-mode: container:worker
exec:
- ip addr add 10.0.2.2/24 dev net0
- ip route replace default via 10.0.2.1
server2:
kind: linux
image: nicolaka/netshoot:latest
network-mode: container:worker2
exec:
- ip addr add 10.0.3.2/24 dev net0
- ip route replace default via 10.0.3.1
server3:
kind: linux
image: nicolaka/netshoot:latest
network-mode: container:worker3
exec:
- ip addr add 10.0.4.2/24 dev net0
- ip route replace default via 10.0.4.1
links:
- endpoints: ["router0:net0", "tor0:net0"]
- endpoints: ["router0:net1", "tor1:net0"]
- endpoints: ["tor0:net1", "server0:net0"]
- endpoints: ["tor0:net2", "server1:net0"]
- endpoints: ["tor1:net1", "server2:net0"]
- endpoints: ["tor1:net2", "server3:net0"]
Ejecute el siguiente comando para crear el entorno experimental de Containerlab.
clab deploy -t topo.yaml
La topología creada se muestra a continuación. Actualmente, solo se establecen conexiones BGP entre los dispositivos tor0, tor1 y router0. Como no hemos establecido la configuración BGP del clúster de Kubernetes a través de CiliumBGPPeeringPolicy, las conexiones BGP entre tor0, tor1 y el Nodo Kubernetes no se han establecido. sido establecido.
Ejecute los siguientes comandos respectivamente para verificar el estado actual de establecimiento de vecinos BGP de tor0, tor1, router0 tres dispositivos de red.
docker exec -it clab-bgp-cplane-demo-tor0 vtysh -c "show bgp ipv4 summary wide"
docker exec -it clab-bgp-cplane-demo-tor1 vtysh -c "show bgp ipv4 summary wide"
docker exec -it clab-bgp-cplane-demo-router0 vtysh -c "show bgp ipv4 summary wide"
Ejecute el siguiente comando para ver las entradas de ruta BGP aprendidas por router0.
docker exec -it clab-bgp-cplane-demo-router0 vtysh -c "show bgp ipv4 wide"
Actualmente hay un total de 8 entradas de enrutamiento y el enrutamiento relacionado con el Pod aún no se ha aprendido.
Con el fin de facilitar a los usuarios una comprensión más intuitiva de la estructura de red del experimento, Containerlab proporciona graph
comandos para generar la topología de red.
clab graph -t topo.yaml
Ingrese http://<IP de host>:50080 en el navegador para ver el mapa de topología generado por Containerlab.
5 Instalar Cilio
En este ejemplo, Helm se usa para instalar Cilium, y los parámetros de configuración de Cilium que debemos ajustar se establecen en el archivo de configuración values.yaml.
# values.yaml
tunnel: disabled
ipam:
mode: kubernetes
ipv4NativeRoutingCIDR: 10.0.0.0/8
# 开启 BGP 功能支持,等同于命令行执行 --enable-bgp-control-plane=true
bgpControlPlane:
enabled: true
k8s:
requireIPv4PodCIDR: true
Ejecute los siguientes comandos para instalar Cilium 1.12 y habilitar la compatibilidad con BGP.
helm repo add cilium https://helm.cilium.io/
helm install -n kube-system cilium cilium/cilium --version v1.12.1 -f values.yaml
Después de esperar a que se inicien todos los Cilium Pods, vuelva a comprobar el estado del nodo de Kubernetes y podrá ver que todos los nodos ya están en estado Listo.
6 nodos Cilium configuran BGP
A continuación, configure CiliumBGPPeeringPolicy para los nodos de Kubernetes en rack0 y rack1 respectivamente. Rack0 y rack1 corresponden a las etiquetas de Nodo respectivamente, que se establecen en el archivo de configuración de Tipo en la Sección 3.
El Nodo de rack0 establece una relación de vecino BGP con tor0, y el Nodo de rack1 establece una relación de vecino BGP con tor1, y automáticamente anuncia el CIDR del Pod al vecino BGP.
# cilium-bgp-peering-policies.yaml
apiVersion: "cilium.io/v2alpha1"
kind: CiliumBGPPeeringPolicy
metadata:
name: rack0
spec:
nodeSelector:
matchLabels:
rack: rack0
virtualRouters:
- localASN: 65010
exportPodCIDR: true # 自动宣告 Pod CIDR
neighbors:
- peerAddress: "10.0.0.1/32" # tor0 的 IP 地址
peerASN: 65010
---
apiVersion: "cilium.io/v2alpha1"
kind: CiliumBGPPeeringPolicy
metadata:
name: rack1
spec:
nodeSelector:
matchLabels:
rack: rack1
virtualRouters:
- localASN: 65011
exportPodCIDR: true
neighbors:
- peerAddress: "10.0.0.2/32" # tor1 的 IP 地址
peerASN: 65011
Ejecute el siguiente comando para aplicar CiliumBGPPeeringPolicy.
kubectl apply -f cilium-bgp-peering-policies.yaml
La topología creada se muestra a continuación. Ahora tor0 y tor1 han establecido vecinos BGP con Kubernetes Node.
Ejecute los siguientes comandos respectivamente para verificar el estado actual de establecimiento de vecinos BGP de tor0, tor1, router0 tres dispositivos de red.
docker exec -it clab-bgp-cplane-demo-tor0 vtysh -c "show bgp ipv4 summary wide"
docker exec -it clab-bgp-cplane-demo-tor1 vtysh -c "show bgp ipv4 summary wide"
docker exec -it clab-bgp-cplane-demo-router0 vtysh -c "show bgp ipv4 summary wide"
Ejecute el siguiente comando para ver las entradas de ruta BGP aprendidas por router0.
docker exec -it clab-bgp-cplane-demo-router0 vtysh -c "show bgp ipv4 wide"
Actualmente hay un total de 12 entradas de ruta y las 4 rutas adicionales son las rutas del segmento de red 10.1.x.0/24 aprendidas de los 4 nodos de Kubernetes.
7 Prueba de validación
Cree un Pod en los nodos donde se encuentran rack0 y rack1 para probar la conectividad de la red.
# nettool.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: nettool-1
name: nettool-1
spec:
containers:
- image: cr7258/nettool:v1
name: nettool-1
nodeSelector:
rack: rack0
---
apiVersion: v1
kind: Pod
metadata:
labels:
run: nettool-2
name: nettool-2
spec:
containers:
- image: cr7258/nettool:v1
name: nettool-2
nodeSelector:
rack: rack1
Ejecute los siguientes comandos para crear 2 Pods de prueba.
kubectl apply -f nettool.yaml
Ver la dirección IP del Pod.
kubectl get pod -o wide
El pod nettool-1 está ubicado en clab-bgp-cplane-demo-worker (servidor1, rack0), la dirección IP es 10.1.2.185; el pod nettool-2 está ubicado en clab-bgp-cplane-demo-worker3 (servidor3 , rack1), la dirección IP es La dirección es 10.1.3.56.
Ejecute el siguiente comando para intentar hacer ping al pod nettool-2 desde el pod nettool-1.
kubectl exec -it nettool-1 -- ping 10.1.3.56
Puede ver que el nettool-1 Pod puede acceder al nettool-2 Pod normalmente.
Luego, use el comando traceroute para observar la dirección de los paquetes de red.
kubectl exec -it nettool-1 -- traceroute -n 10.1.3.56
El paquete se envía desde nettool-1 Pod y pasa por:
- 1. La interfaz cilium_host del servidor 1 : la ruta predeterminada del Pod en la red de Cilium apunta al cilium_host local. cilium_host y cilium_net son un dispositivo de par veth. Cilium utiliza tablas ARP codificadas para obligar a que el próximo salto del tráfico del Pod sea secuestrado hacia el lado del host del par veth.
- 2. La interfaz net2 de tor0 .
- 3. La interfaz lo0 del router0: los tres dispositivos de red tor0, tor1 y router0 establecen una relación de vecino BGP a través de la interfaz de bucle invertido local lo0. Esto puede mejorar la solidez del vecino BGP en el caso de múltiples copias de seguridad de enlaces físicos. La relación de vecino se ve afectado cuando falla una interfaz física.
- 4. La interfaz lo0 de tor1 .
- 5. La interfaz net0 de server3 .
8 Limpiar el medio ambiente
Ejecute los siguientes comandos para limpiar el entorno experimental creado por Containerlab y Kind.
clab destroy -t topo.yaml
kind delete clusters clab-bgp-cplane-demo
9 Referencias
- [1] GoBGP: https://osrg.github.io/gobgp/
- [2] Tipo: https://kind.sigs.k8s.io/
- [3] laboratorio de contenedores: https://containerlab.dev/
- [4] Ejemplos de laboratorio: https://containerlab.dev/lab-examples/lab-examples/
- [5] Tejido Clos de 5 etapas: https://containerlab.dev/lab-examples/min-5clos/
- [6] BGP CON CILIUM: https://nicovibert.com/2022/07/21/bgp-with-cilium/
- [7] CONTINAERlab + KinD implementa el clúster K8s en la red en segundos: https://www.bilibili.com/video/BV1Qa411d7wm?spm_id_from=333.337.search-card.all.click&vd_source=1c0f4059dae237b29416579c3a5d326e
- [8] Descripción general de la red Cilium: https://www.koenli.com/fcdddb4a.html
- [9] Plano de control BGP de Cilium: https://docs.cilium.io/en/stable/gettingstarted/bgp-control-plane/#cilium-bgp-control-plane
- [10] Cilium 1.12: ingreso, multiclúster, Service Mesh, cargas de trabajo externas y mucho más: https://isovalent.com/blog/post/cilium-release-112/#vtep-support
- [11] Cilium 1.10: WireGuard, compatibilidad con BGP, puerta de enlace IP de salida, nueva CLI de Cilium, balanceador de carga XDP, integración con la nube de Alibaba y más: https://cilium.io/blog/2021/05/20/cilium-110/
- [12] Vida de un paquete en Cilium: exploración de campo de la ruta de reenvío de pod a servicio y lógica de procesamiento BPF: https://arthurchiao.art/blog/cilium-life-of-a-packet-pod-to-service - es/