Skip to content

Latest commit

 

History

History
416 lines (358 loc) · 13.6 KB

TP13.md

File metadata and controls

416 lines (358 loc) · 13.6 KB

Routage et Annonces BGP

Ce TP se déroule sur un cluster KinD.

Sommaire

On utiliser cilium en version 1.6.1 et l'implementation GoGBP (via CRD) et non MetalLB (via ConfigMap)

But du TP

  • Construire en lab une mini matrice de Clos (1 spine, 2 leaf), y connecter 4 Nodes.
  • Activer BGP au niveau des Nodes pour diffuser les réseaux CIDRs des Pods.

Etape 0 Préparation

Connectez-vous en SSH sur la VM auquel l'animateur vous donne accès.
Containerlab et KinD y sont déjà installés.

Etape 1 Lancement de KinD

Nettoyons les eventuels clusters déjà présents :

cd /home/cilium_lab/bgp-cplane-demo
./clean-kind.sh 

Lançons le cluster avec un script simple :

./01-build-kind-cluster.sh 

Nous finissons pas obtenir :

[..]
---
Kubernetes control plane is running at https://127.0.0.1:36969
CoreDNS is running at https://127.0.0.1:36969/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
---
NAME                                 STATUS     ROLES           AGE   VERSION
clab-bgp-cplane-demo-control-plane   NotReady   control-plane   28s   v1.24.0
clab-bgp-cplane-demo-worker          NotReady   <none>          5s    v1.24.0
clab-bgp-cplane-demo-worker2         NotReady   <none>          5s    v1.24.0
clab-bgp-cplane-demo-worker3         NotReady   <none>          5s    v1.24.0

Les noeuds restent en NotReady car le CNI n’est pas encore installé

Nous avons appliqué un label nommé rack, qui permet de grouper les server (dérouler tout à droite de la fenetre ci dessous) :

# kubectl get node --show-labels
NAME                                 STATUS   ROLES           AGE   VERSION   LABELS
clab-bgp-cplane-demo-control-plane   NotReady    control-plane   32m   v1.24.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=clab-bgp-cplane-demo-control-plane,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=,rack=rack0
clab-bgp-cplane-demo-worker          NotReady    <none>          32m   v1.24.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=clab-bgp-cplane-demo-worker,kubernetes.io/os=linux,rack=rack0
clab-bgp-cplane-demo-worker2         NotReady    <none>          32m   v1.24.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=clab-bgp-cplane-demo-worker2,kubernetes.io/os=linux,rack=rack1
clab-bgp-cplane-demo-worker3         NotReady    <none>          32m   v1.24.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=clab-bgp-cplane-demo-worker3,kubernetes.io/os=linux,rack=rack1

Etape 2 Déploiement de Containerlab

Créeons un lab avec containerlab, consitué de 4 Node (server0 à server3), chaque paire étant connectée sur un switch ToR (tor0 et tor1), eux-même interconnectés sur un routeur central, router0.

bgp-cilium

La topologie est décrite dans le fichier topo.yaml.

./02-deploy-containerlab.sh 

On obtient :

Etape 3 Installation de Cilium

IMPORTANT : Tout d'abord vérifier que le fichier values.yaml a le contenu suiviant :

routingMode: native
ipv4NativeRoutingCIDR: "10.0.0.0/8"
bgpControlPlane:
  enabled: true
k8s:
  requireIPv4PodCIR: true
ipam:
  mode: kubernetes
hubble:
  enabled: true
  relay:
    enabled: true
  ui:
    enabled: true

Ensuite, installons le CNI Cilium :

./03-install-cilium.sh

Au final, cilium est prêt :

# cilium status
    /¯¯\
 /¯¯\__/¯¯\    Cilium:         OK
 \__/¯¯\__/    Operator:       OK
 /¯¯\__/¯¯\    Hubble:         OK
 \__/¯¯\__/    ClusterMesh:    disabled
    \__/

Deployment        hubble-ui          Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet         cilium             Desired: 4, Ready: 4/4, Available: 4/4
Deployment        hubble-relay       Desired: 1, Ready: 1/1, Available: 1/1
Deployment        cilium-operator    Desired: 2, Ready: 2/2, Available: 2/2
Containers:       cilium             Running: 4
                  hubble-relay       Running: 1
                  cilium-operator    Running: 2
                  hubble-ui          Running: 1

Etape 4 Affichage des routes BGP

Nous avons crée un simple script qui se connecte dans un des switches (tor0, tor1 ou router0) et affiche la table BGP (show bgp ipv4 summary wide , show bgp ipv4 wide)

./showbgp.sh router0

On obtient cela :

On constate le peering vers tor0 et tor1.

Regardons vu de tor0 :

./showbgp.sh tor0

On obtient cela :

Nous constatons qu'aucun préfixe n'est échange avec les server0 et server1.

Etape 5 Activation de BGP dans Cilium

Creeons notre BGP advertisement avec le fichier cilium-bgp-advertisement.yaml :

apiVersion: cilium.io/v2alpha1
kind: CiliumBGPAdvertisement
metadata:
  name: bgp-advertisements
  labels:
    advertise: bgp
spec:
  advertisements:
    - advertisementType: "Service"
      service:
        addresses:
          - ClusterIP
          - ExternalIP
          - LoadBalancerIP
      selector:
        matchExpressions:
          - { key: bgp, operator: In, values: [ blue ] }

Appliquons ces CRD :

kubectl apply -f cilium-bgp-advertisement.yaml

Activons BGP au niveau des Nodes grâce aux 2 politiques Cilium suivantes (1 par rack) :

## cilium-bgp-peering-policies.yaml 
---
apiVersion: "cilium.io/v2alpha1"
kind: CiliumBGPPeeringPolicy
metadata:
  name: rack0
  namespace: kube-system
spec:
  nodeSelector:
    matchLabels:
      rack: "rack0"
  virtualRouters:
    - localASN: 65010
      exportPodCIDR: true
      neighbors:
        - peerAddress: "10.0.0.1/32"
          peerASN: 65010
      serviceSelector:
        matchExpressions:
          - {key: 'bgp', operator: In, values: ['blue']}
---
apiVersion: "cilium.io/v2alpha1"
kind: CiliumBGPPeeringPolicy
metadata:
  name: "rack1"
  namespace: kube-system
spec:
  nodeSelector:
    matchLabels:
      rack: rack1
  virtualRouters:
    - localASN: 65011
      exportPodCIDR: true
      neighbors:
        - peerAddress: "10.0.0.2/32"
          peerASN: 65011
      serviceSelector:
        matchExpressions:
          - {key: 'bgp', operator: In, values: ['blue']}

Appliquons cette politique :

# ./04-enable-bgp-cilium.sh
ciliumbgppeeringpolicy.cilium.io/rack0 created
ciliumbgppeeringpolicy.cilium.io/rack1 created 

Etape 6 Vérification du routage

Regardons à nouveau les routeurs sur router0 :

Nous voyons les CIDRs des Pods apparaitre !

Nous laissons au lecteur le soin de déployer un DaemonSet (image=nginx par exemple), et de vérifier que les préfixes sont bien échangés en réalisant des connexions TCP/80 internodes.

Bonus L4LB

Reconfigurons les paramètres Helm contenu dans le fichier values.yaml :

ipv4NativeRoutingCIDR: "10.0.0.0/8"
kubeProxyReplacement: true
## add-on
externalIPs:
  enabled: true
loadBalancer:
  algorithm: maglev
bgp:
  ## desactive Metal LB
  enabled: false
  announce:
    loadbalancerIP: true
    podCIDR: true
## 

bgpControlPlane:
  ## active GoBGP
  enabled: true
k8s:
  requireIPv4PodCIR: true
ipam:
  mode: kubernetes

Appliquons ces modifications à Cilium :

C_VERSION="1.16.1"; helm upgrade --install --namespace kube-system --repo https://helm.cilium.io cilium cilium --values values.yaml --version $C_VERSION

Il faut également créer le fichier cilium-iploadbalancer-ippool.yaml suivant :

apiVersion: "cilium.io/v2alpha1"
kind: CiliumLoadBalancerIPPool
metadata:
  name: "blue-pool"
spec:
  blocks:
  - cidr: "192.0.2.0/24"
  serviceSelector:
    matchExpressions:
      - {key: bgp, operator: In, values: [blue, cyan]} 

Appliquons la:

 kubectl apply -f cilium-iploadbalancer-ippool.yaml

Redémarrons les DameonSet Cilium :

kubectl rollout restart ds/cilium  -n kube-system

Pour activer la fonctionnalité LB, il nous faut un service à publier. Utilisons celui-là (notez le label qui activera la publication BGP):

## lbsvc.yaml
apiVersion: v1
kind: Service
metadata:
  name: test-lb
  labels:
    bgp: blue
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    svc: test-lb
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      svc: test-lb
  template:
    metadata:
      labels:
        svc: test-lb
    spec:
      containers:
      - name: web
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        readinessProbe:
          httpGet:
            path: /
            port: 80

Et appliquons-le :

kubectl apply -f lbsvc.yaml

On constate que le préfixe 192.0.2.0/32 est annoncé :

./showbgp.sh tor0
----- tor0 ----

IPv4 Unicast Summary (VRF default):
BGP router identifier 10.0.0.1, local AS number 65010 vrf-id 0
BGP table version 39
RIB entries 25, using 4600 bytes of memory
Peers 3, using 2149 KiB of memory
Peer groups 2, using 128 bytes of memory

Neighbor                                     V         AS    LocalAS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
router0(net0)                                4      65000      65010       812       815        0    0    0 00:38:54            8       14 N/A
clab-bgp-cplane-demo-control-plane(10.0.1.2) 4      65010      65010       558       579        0    0    0 00:00:31            2       11 N/A
clab-bgp-cplane-demo-worker(10.0.2.2)        4      65010      65010       563       586        0    0    0 00:00:34            2       11 N/A

Total number of neighbors 3
--
BGP table version is 39, local router ID is 10.0.0.1, vrf id 0
Default local pref 100, local AS 65010
Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

   Network                                      Next Hop                                  Metric LocPrf Weight Path
*> 0.0.0.0/0                                    net0                                                         0 65000 i
*> 10.0.0.0/32                                  net0                                           0             0 65000 ?
*> 10.0.0.1/32                                  0.0.0.0(tor0)                                  0         32768 ?
*> 10.0.0.2/32                                  net0                                                         0 65000 65011 ?
*> 10.0.1.0/24                                  0.0.0.0(tor0)                                  0         32768 ?
*> 10.0.2.0/24                                  0.0.0.0(tor0)                                  0         32768 ?
*> 10.0.3.0/24                                  net0                                                         0 65000 65011 ?
*> 10.0.4.0/24                                  net0                                                         0 65000 65011 ?
*>i10.244.0.0/24                                10.0.1.2(clab-bgp-cplane-demo-control-plane)
                                                 0      0 ?
*>i10.244.1.0/24                                10.0.2.2(clab-bgp-cplane-demo-worker)                 0      0 ?
*> 10.244.2.0/24                                net0                                                         0 65000 65011 i
*> 10.244.3.0/24                                net0                                                         0 65000 65011 i
*> 172.20.20.0/24                               net0                                           0             0 65000 ?
*>i192.0.2.0/32                                 10.0.1.2(clab-bgp-cplane-demo-control-plane)
                                                 0      0 ?
*=i                                             10.0.2.2(clab-bgp-cplane-demo-worker)                 0      0 ?
Displayed  14 routes and 15 total paths

Et l'IP LB est bien attribuée :

# kubectl get svc
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes       ClusterIP      10.245.0.1      <none>        443/TCP        51m
svc-echoserver   LoadBalancer   10.245.137.44   192.0.2.0     80:30516/TCP   35m

On peut tester :

# kubectl run debug2 -it --rm --image=alpine -- sh
If you don't see a command prompt, try pressing enter.
/ # curl 192.0.2.0
sh: curl: not found
/ # wget 192.0.2.0
Connecting to 192.0.2.0 (192.0.2.0:80)
saving to 'index.html'
index.html           100% |***********************************************************************************|  1868  0:00:00 ETA
'index.html' saved
/ # 

Pour note, l'annonce BGP de l'IP LoadBalancer n'a lieu que si au moins 1 Pod fait partie du svc.

Revenir au sommaire | TP Suivant